From 56c05737aa0da4a5003a320a3612b0794a5a3983 Mon Sep 17 00:00:00 2001 From: Alexis Tyler Date: Thu, 28 Jun 2018 20:09:45 +0930 Subject: [PATCH 01/15] URL -> Url (#148) --- index.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/index.js b/index.js index a48340e..b88077a 100644 --- a/index.js +++ b/index.js @@ -58,9 +58,9 @@ function lolcation(loc) { , key; if ('blob:' === loc.protocol) { - finaldestination = new URL(unescape(loc.pathname), {}); + finaldestination = new Url(unescape(loc.pathname), {}); } else if ('string' === type) { - finaldestination = new URL(loc, {}); + finaldestination = new Url(loc, {}); for (key in ignore) delete finaldestination[key]; } else if ('object' === type) { for (key in loc) { @@ -146,9 +146,9 @@ function resolve(relative, base) { * @param {Boolean|Function} parser Parser for the query string. * @api public */ -function URL(address, location, parser) { - if (!(this instanceof URL)) { - return new URL(address, location, parser); +function Url(address, location, parser) { + if (!(this instanceof Url)) { + return new Url(address, location, parser); } var relative, extracted, parse, instruction, index, key @@ -400,14 +400,14 @@ function toString(stringify) { return result; } -URL.prototype = { set: set, toString: toString }; +Url.prototype = { set: set, toString: toString }; // // Expose the URL parser and some additional properties that might be useful for // others or testing. // -URL.extractProtocol = extractProtocol; -URL.location = lolcation; -URL.qs = qs; +Url.extractProtocol = extractProtocol; +Url.location = lolcation; +Url.qs = qs; -module.exports = URL; +module.exports = Url; From da8cddbccc48f60b1b08f1b59f2e38ca90e3d6cf Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Thu, 28 Jun 2018 12:46:38 +0200 Subject: [PATCH 02/15] [dist] 1.4.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fdeeb6f..4234016 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "url-parse", - "version": "1.4.1", + "version": "1.4.2", "description": "Small footprint URL parser that works seamlessly across Node.js and browser environments", "main": "index.js", "scripts": { From 3cc810c7d1a6653ef2d6d6a8d815702a455d151d Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Fri, 29 Jun 2018 07:18:04 +0200 Subject: [PATCH 03/15] [test] Remove Opera from the list of browsers to test --- test/browser.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/browser.js b/test/browser.js index a942d21..8cc3203 100644 --- a/test/browser.js +++ b/test/browser.js @@ -12,7 +12,6 @@ const platforms = sauceBrowsers([ { name: 'firefox', version: ['oldest', 'latest'] }, { name: 'internet explorer', version: 'oldest..latest' }, { name: 'iphone', version: ['oldest', 'latest'] }, - { name: 'opera', version: 'oldest..latest' }, { name: 'safari', version: 'oldest..latest' }, { name: 'microsoftedge', version: 'oldest..latest' } ]).then((platforms) => { From f60fa4e20d72d1b7d11252868f93d7aa5f4cb202 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" Date: Fri, 29 Jun 2018 07:41:21 +0200 Subject: [PATCH 04/15] chore(package): update sauce-browsers to version 2.0.0 (#149) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4234016..05a0c18 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "mocha": "^5.1.1", "nyc": "^12.0.1", "pre-commit": "^1.2.0", - "sauce-browsers": "^1.2.0", + "sauce-browsers": "^2.0.0", "sauce-test": "^1.3.3", "uglify-js": "^3.3.21" } From 53b1794e54d0711ceb52505e0f74145270570d5a Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Sun, 29 Jul 2018 14:26:05 +0200 Subject: [PATCH 05/15] [security] Sanitize paths, hosts before parsing. --- index.js | 30 +++++++++++++++++++++--------- test/test.js | 29 +++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/index.js b/index.js index b88077a..dcc4b41 100644 --- a/index.js +++ b/index.js @@ -20,6 +20,9 @@ var required = require('requires-port') var rules = [ ['#', 'hash'], // Extract from the back. ['?', 'query'], // Extract from the back. + function sanitize(address) { // Sanitize what is left of the address + return address.replace('\\', '/'); + }, ['/', 'pathname'], // Extract from the back. ['@', 'auth', 1], // Extract from the front. [NaN, 'host', undefined, 1, 1], // Set left over value. @@ -47,7 +50,7 @@ var ignore = { hash: 1, query: 1 }; * * @param {Object|String} loc Optional default location object. * @returns {Object} lolcation object. - * @api public + * @public */ function lolcation(loc) { var location = global && global.location || {}; @@ -89,7 +92,7 @@ function lolcation(loc) { * * @param {String} address URL we want to extract from. * @return {ProtocolExtract} Extracted information. - * @api private + * @private */ function extractProtocol(address) { var match = protocolre.exec(address); @@ -107,7 +110,7 @@ function extractProtocol(address) { * @param {String} relative Pathname of the relative URL. * @param {String} base Pathname of the base URL. * @return {String} Resolved pathname. - * @api private + * @private */ function resolve(relative, base) { var path = (base || '/').split('/').slice(0, -1).concat(relative.split('/')) @@ -140,11 +143,14 @@ function resolve(relative, base) { * create an actual constructor as it's much more memory efficient and * faster and it pleases my OCD. * + * It is worth noting that we should not use `URL` as class name to prevent + * clashes with the global URL instance that got introduced in browsers. + * * @constructor * @param {String} address URL we want to parse. * @param {Object|String} location Location defaults for relative paths. * @param {Boolean|Function} parser Parser for the query string. - * @api public + * @private */ function Url(address, location, parser) { if (!(this instanceof Url)) { @@ -190,10 +196,16 @@ function Url(address, location, parser) { // When the authority component is absent the URL starts with a path // component. // - if (!extracted.slashes) instructions[2] = [/(.*)/, 'pathname']; + if (!extracted.slashes) instructions[3] = [/(.*)/, 'pathname']; for (; i < instructions.length; i++) { instruction = instructions[i]; + + if (typeof instruction === 'function') { + address = instruction(address); + continue; + } + parse = instruction[0]; key = instruction[1]; @@ -284,8 +296,8 @@ function Url(address, location, parser) { * used to parse the query. * When setting the protocol, double slash will be * removed from the final url if it is true. - * @returns {URL} - * @api public + * @returns {URL} URL instance for chaining. + * @public */ function set(part, value, fn) { var url = this; @@ -370,8 +382,8 @@ function set(part, value, fn) { * Transform the properties back in to a valid and full URL string. * * @param {Function} stringify Optional query stringify function. - * @returns {String} - * @api public + * @returns {String} Compiled version of the URL. + * @public */ function toString(stringify) { if (!stringify || 'function' !== typeof stringify) stringify = qs.stringify; diff --git a/test/test.js b/test/test.js index 8f47aea..e7a8651 100644 --- a/test/test.js +++ b/test/test.js @@ -192,6 +192,28 @@ describe('url-parse', function () { assume(parsed.pathname).equals('/b/c'); }); + it('ignores \\ in pathnames', function () { + var url = 'http://google.com:80\\@yahoo.com/#what\\is going on' + , parsed = parse(url); + + assume(parsed.port).equals(''); + assume(parsed.username).equals(''); + assume(parsed.password).equals(''); + assume(parsed.hostname).equals('google.com'); + assume(parsed.hash).equals('#what\\is going on'); + + parsed = parse('//\\what-is-up.com'); + assume(parsed.pathname).equals('/what-is-up.com'); + }); + + it('correctly ignores multiple slashes //', function () { + var url = '////what-is-up.com' + , parsed = parse(url); + + assume(parsed.host).equals(''); + assume(parsed.hostname).equals(''); + }); + describe('origin', function () { it('generates an origin property', function () { var url = 'http://google.com:80/pathname' @@ -252,6 +274,13 @@ describe('url-parse', function () { o = parse('wss://google.com:80/pathname'); assume(o.origin).equals('wss://google.com:80'); }); + + it('maintains the port number for non-default port numbers', function () { + var parsed = parse('http://google.com:8080/pathname'); + + assume(parsed.host).equals('http://google.com:8080'); + assume(parsed.href).equals('http://google.com:8080/pathname'); + }); }); describe('protocol', function () { From d7b582ec1243e8024e60ac0b62d2569c939ef5de Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Sun, 29 Jul 2018 14:42:38 +0200 Subject: [PATCH 06/15] [security] Added missing SECURITY.md --- SECURITY.md | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..368469d --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,47 @@ +# Security Guidelines + +Please contact us directly at **security@3rd-Eden.com** for any bug that might +impact the security of this project. Please prefix the subject of your email +with `[security]` in lowercase and square brackets. Our email filters will +automatically prevent these messages from being moved to our spam box. All +emails that do not include security vulnerabilities will be removed and blocked +instantly. + +In addition to a dedicated email address to receive security related reports, +we also have a [Hacker1 account][hacker1] that can be used be used for +communicating security related issues. + +You will receive an acknowledgement of your report within **24 hours** of +notification. + +## Exceptions + +If you do not receive an acknowledgement within the said time frame please give +us the benefit of the doubt as it's possible that we haven't seen it yet. In +this case please send us a message **without details** using one of the +following methods: + +- Give a poke on Twitter [@3rdEden](https://twitter.com/3rdEden) +- Contact the lead developers of this project on their personal e-mails. You + can find the e-mails in the git logs, for example using the following command: + `git --no-pager show -s --format='%an <%ae>' ` where `` is the + SHA1 of their latest commit in the project. + +Once we have acknowledged receipt of your report and confirmed the bug +ourselves we will work with you to fix the vulnerability and publicly +acknowledge your responsible disclosure, if you wish. + +## History + +> url-parse returns wrong hostname which leads to multiple vulnerabilities such +> as SSRF, Open Redirect, Bypass Authentication Protocol. + +- Hacker1 report: https://hackerone.com/reports/384029 +- Reported by [lolwaleet](https://hackerone.com/lolwalee) +- Triaged by [Liran Tal](https://hackerone.com/lirantal) +- Fixed in: 1.4.3 + +--- + +[twitter]: https://twitter.com/3rdEden +[hacker1]: https://hackerone.com/3rdeden From 426e92933d1eca6469bf3490fd76676f80ad0108 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Sun, 29 Jul 2018 14:43:48 +0200 Subject: [PATCH 07/15] [dist] 1.4.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 05a0c18..3995801 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "url-parse", - "version": "1.4.2", + "version": "1.4.3", "description": "Small footprint URL parser that works seamlessly across Node.js and browser environments", "main": "index.js", "scripts": { From 541b70fe23fa1e1a4d9e78e95de80c053f42e436 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Sun, 29 Jul 2018 14:51:12 +0200 Subject: [PATCH 08/15] [test] Fix incorrect test, was not supposted to be added with previous commit --- test/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test.js b/test/test.js index e7a8651..4302d9a 100644 --- a/test/test.js +++ b/test/test.js @@ -278,7 +278,7 @@ describe('url-parse', function () { it('maintains the port number for non-default port numbers', function () { var parsed = parse('http://google.com:8080/pathname'); - assume(parsed.host).equals('http://google.com:8080'); + assume(parsed.host).equals('google.com:8080'); assume(parsed.href).equals('http://google.com:8080/pathname'); }); }); From a84b506779eb0dad952254c0e0c6736522638208 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Sun, 29 Jul 2018 15:11:31 +0200 Subject: [PATCH 09/15] [sec] Updated reporter details --- SECURITY.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/SECURITY.md b/SECURITY.md index 368469d..bf69953 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -36,8 +36,11 @@ acknowledge your responsible disclosure, if you wish. > url-parse returns wrong hostname which leads to multiple vulnerabilities such > as SSRF, Open Redirect, Bypass Authentication Protocol. +- **Reporter credits** + - Hacker1: [lolwaleet](https://hackerone.com/lolwalee) + - Twitter: [@ahm3dsec](https://twitter.com/ahm3dsec) + - Blog: [0xahmed.ninja](https://0xahmed.ninja) - Hacker1 report: https://hackerone.com/reports/384029 -- Reported by [lolwaleet](https://hackerone.com/lolwalee) - Triaged by [Liran Tal](https://hackerone.com/lirantal) - Fixed in: 1.4.3 From 1c19d5a894e041e7aa905552e8e218ab63d97a54 Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Sun, 29 Jul 2018 15:48:31 +0200 Subject: [PATCH 10/15] [security] Fix typo in SECURITY.md (#151) --- SECURITY.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index bf69953..ea5a99c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -8,8 +8,8 @@ emails that do not include security vulnerabilities will be removed and blocked instantly. In addition to a dedicated email address to receive security related reports, -we also have a [Hacker1 account][hacker1] that can be used be used for -communicating security related issues. +we also have a [Hacker1 account][hacker1] that can be used for communicating +security related issues. You will receive an acknowledgement of your report within **24 hours** of notification. From 4e14338495fe58a167de6abda90953459c0828d5 Mon Sep 17 00:00:00 2001 From: Glenn Matthys Date: Sun, 5 Aug 2018 07:08:29 +0200 Subject: [PATCH 11/15] [codestyle] Mark location and parser in JSDoc as optional (#153) --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index dcc4b41..b529a2e 100644 --- a/index.js +++ b/index.js @@ -148,8 +148,8 @@ function resolve(relative, base) { * * @constructor * @param {String} address URL we want to parse. - * @param {Object|String} location Location defaults for relative paths. - * @param {Boolean|Function} parser Parser for the query string. + * @param {Object|String} [location] Location defaults for relative paths. + * @param {Boolean|Function} [parser] Parser for the query string. * @private */ function Url(address, location, parser) { From 9fb86cfc8d9f09a0e6ab24eedede4a9959972c2c Mon Sep 17 00:00:00 2001 From: niftylettuce Date: Fri, 21 Sep 2018 00:34:45 -0500 Subject: [PATCH 12/15] [doc] Replace URL with Url (#158) --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d9dfd7a..f81f919 100644 --- a/README.md +++ b/README.md @@ -38,14 +38,14 @@ All examples assume that this library is bootstrapped using: ```js 'use strict'; -var URL = require('url-parse'); +var Url = require('url-parse'); ``` To parse an URL simply call the `URL` method with the URL that needs to be transformed into an object. ```js -var url = new URL('https://github.com/foo/bar'); +var url = new Url('https://github.com/foo/bar'); ``` The `new` keyword is optional but it will save you an extra function invocation. @@ -100,7 +100,7 @@ var parse = require('url-parse'); parse('hostname', {}); ``` -### URL.set(key, value) +### Url.set(key, value) A simple helper function to change parts of the URL and propagating it through all properties. When you set a new `host` you want the same value to be applied @@ -117,7 +117,7 @@ console.log(parsed.href); // http://yahoo.com/parse-things It's aware of default ports so you cannot set a port 80 on an URL which has `http` as protocol. -### URL.toString() +### Url.toString() The returned `url` object comes with a custom `toString` method which will generate a full URL again when called. The method accepts an extra function From 7781ad86f49d082f9cbdcae3cbc46b28797840d6 Mon Sep 17 00:00:00 2001 From: Ben Laniado Date: Mon, 5 Nov 2018 15:34:27 +0200 Subject: [PATCH 13/15] [fix] global is not defined (#160) * global is not defined #119 * better handling of global * Co-Authored-By: benland * globalVar is always defined * Co-Authored-By: benland --- index.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index b529a2e..e9d5a6f 100644 --- a/index.js +++ b/index.js @@ -53,7 +53,17 @@ var ignore = { hash: 1, query: 1 }; * @public */ function lolcation(loc) { - var location = global && global.location || {}; + var globalVar; + + if (typeof window !== 'undefined') + globalVar = window; + else if (typeof global !== 'undefined') + globalVar = global; + else if (typeof self !== 'undefined') + globalVar = self; + else + globalVar = {}; + var location = globalVar.location || {}; loc = loc || location; var finaldestination = {} From b15fd4a16270f39f5d66fd8d64a3f820df8c38e3 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Mon, 5 Nov 2018 14:35:26 +0100 Subject: [PATCH 14/15] [ocd] code style --- index.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index e9d5a6f..c616bfd 100644 --- a/index.js +++ b/index.js @@ -55,14 +55,11 @@ var ignore = { hash: 1, query: 1 }; function lolcation(loc) { var globalVar; - if (typeof window !== 'undefined') - globalVar = window; - else if (typeof global !== 'undefined') - globalVar = global; - else if (typeof self !== 'undefined') - globalVar = self; - else - globalVar = {}; + if (typeof window !== 'undefined') globalVar = window; + else if (typeof global !== 'undefined') globalVar = global; + else if (typeof self !== 'undefined') globalVar = self; + else globalVar = {}; + var location = globalVar.location || {}; loc = loc || location; From bc9da1ec19a86199be663a7f0ba40091834d73f7 Mon Sep 17 00:00:00 2001 From: Arnout Kazemier Date: Mon, 5 Nov 2018 14:36:22 +0100 Subject: [PATCH 15/15] [dist] 1.4.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3995801..40cb3f0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "url-parse", - "version": "1.4.3", + "version": "1.4.4", "description": "Small footprint URL parser that works seamlessly across Node.js and browser environments", "main": "index.js", "scripts": {