summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatteo Collina <hello@matteocollina.com>2018-09-10 12:57:07 +0200
committerRod Vagg <rod@vagg.org>2018-11-28 11:36:34 +1100
commitb77f699a84219702ccef6387882c0fdcb58529bb (patch)
tree184b40b30b832b5caf6fd28219144f1167b13b59
parentee618a7ab239c98d945c723a4e225bc409151736 (diff)
downloadandroid-node-v8-b77f699a84219702ccef6387882c0fdcb58529bb.tar.gz
android-node-v8-b77f699a84219702ccef6387882c0fdcb58529bb.tar.bz2
android-node-v8-b77f699a84219702ccef6387882c0fdcb58529bb.zip
url: avoid hostname spoofing w/ javascript protocol
CVE-2018-12123 Fixes: https://github.com/nodejs-private/security/issues/205 PR-URL: https://github.com/nodejs-private/node-private/pull/145 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
-rw-r--r--lib/url.js4
-rw-r--r--test/parallel/test-url-parse-format.js55
2 files changed, 57 insertions, 2 deletions
diff --git a/lib/url.js b/lib/url.js
index db7369fed0..dfdb565cec 100644
--- a/lib/url.js
+++ b/lib/url.js
@@ -267,13 +267,13 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) {
if (slashesDenoteHost || proto || hostPattern.test(rest)) {
var slashes = rest.charCodeAt(0) === CHAR_FORWARD_SLASH &&
rest.charCodeAt(1) === CHAR_FORWARD_SLASH;
- if (slashes && !(proto && hostlessProtocol[proto])) {
+ if (slashes && !(proto && hostlessProtocol[lowerProto])) {
rest = rest.slice(2);
this.slashes = true;
}
}
- if (!hostlessProtocol[proto] &&
+ if (!hostlessProtocol[lowerProto] &&
(slashes || (proto && !slashedProtocol[proto]))) {
// there's a hostname.
diff --git a/test/parallel/test-url-parse-format.js b/test/parallel/test-url-parse-format.js
index f4e72ee5ef..b18a5fe585 100644
--- a/test/parallel/test-url-parse-format.js
+++ b/test/parallel/test-url-parse-format.js
@@ -890,6 +890,39 @@ const parseTests = {
pathname: '/*',
path: '/*',
href: 'https:///*'
+ },
+
+ // The following two URLs are the same, but they differ for
+ // a capital A: it is important that we verify that the protocol
+ // is checked in a case-insensitive manner.
+ 'javascript:alert(1);a=\x27@white-listed.com\x27': {
+ protocol: 'javascript:',
+ slashes: null,
+ auth: null,
+ host: null,
+ port: null,
+ hostname: null,
+ hash: null,
+ search: null,
+ query: null,
+ pathname: "alert(1);a='@white-listed.com'",
+ path: "alert(1);a='@white-listed.com'",
+ href: "javascript:alert(1);a='@white-listed.com'"
+ },
+
+ 'javAscript:alert(1);a=\x27@white-listed.com\x27': {
+ protocol: 'javascript:',
+ slashes: null,
+ auth: null,
+ host: null,
+ port: null,
+ hostname: null,
+ hash: null,
+ search: null,
+ query: null,
+ pathname: "alert(1);a='@white-listed.com'",
+ path: "alert(1);a='@white-listed.com'",
+ href: "javascript:alert(1);a='@white-listed.com'"
}
};
@@ -921,3 +954,25 @@ for (const u in parseTests) {
assert.strictEqual(actual, expected,
`format(${u}) == ${u}\nactual:${actual}`);
}
+
+{
+ const parsed = url.parse('http://nodejs.org/')
+ .resolveObject('jAvascript:alert(1);a=\x27@white-listed.com\x27');
+
+ const expected = Object.assign(new url.Url(), {
+ protocol: 'javascript:',
+ slashes: null,
+ auth: null,
+ host: null,
+ port: null,
+ hostname: null,
+ hash: null,
+ search: null,
+ query: null,
+ pathname: "alert(1);a='@white-listed.com'",
+ path: "alert(1);a='@white-listed.com'",
+ href: "javascript:alert(1);a='@white-listed.com'"
+ });
+
+ assert.deepStrictEqual(parsed, expected);
+}