mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
url: improve port validation
If a port is not a number, throw rather than treating the `:` that delineates the port as part of the path. This is consistent with WHATWG URL and also mitigates hostname-spoofing. Concerns about hostname-spoofing were raised and presented in excellent detail by pyozzi-toss (pyozzi@toss.im/Security-Tech Team in Toss). PR-URL: https://github.com/nodejs/node/pull/45012 Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
@@ -383,7 +383,7 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) {
|
||||
|
||||
// validate a little.
|
||||
if (!ipv6Hostname) {
|
||||
rest = getHostname(this, rest, hostname);
|
||||
rest = getHostname(this, rest, hostname, url);
|
||||
}
|
||||
|
||||
if (this.hostname.length > hostnameMaxLen) {
|
||||
@@ -502,7 +502,7 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) {
|
||||
return this;
|
||||
};
|
||||
|
||||
function getHostname(self, rest, hostname) {
|
||||
function getHostname(self, rest, hostname, url) {
|
||||
for (let i = 0; i < hostname.length; ++i) {
|
||||
const code = hostname.charCodeAt(i);
|
||||
const isValid = (code !== CHAR_FORWARD_SLASH &&
|
||||
@@ -512,6 +512,10 @@ function getHostname(self, rest, hostname) {
|
||||
code !== CHAR_COLON);
|
||||
|
||||
if (!isValid) {
|
||||
// If leftover starts with :, then it represents an invalid port.
|
||||
if (hostname.charCodeAt(i) === 58) {
|
||||
throw new ERR_INVALID_URL(url);
|
||||
}
|
||||
self.hostname = hostname.slice(0, i);
|
||||
return `/${hostname.slice(i)}${rest}`;
|
||||
}
|
||||
|
||||
@@ -865,22 +865,6 @@ const parseTests = {
|
||||
href: 'http://a%0D%22%20%09%0A%3C\'b:b@c/%0D%0Ad/e?f'
|
||||
},
|
||||
|
||||
// Git urls used by npm
|
||||
'git+ssh://git@github.com:npm/npm': {
|
||||
protocol: 'git+ssh:',
|
||||
slashes: true,
|
||||
auth: 'git',
|
||||
host: 'github.com',
|
||||
port: null,
|
||||
hostname: 'github.com',
|
||||
hash: null,
|
||||
search: null,
|
||||
query: null,
|
||||
pathname: '/:npm/npm',
|
||||
path: '/:npm/npm',
|
||||
href: 'git+ssh://git@github.com/:npm/npm'
|
||||
},
|
||||
|
||||
'https://*': {
|
||||
protocol: 'https:',
|
||||
slashes: true,
|
||||
|
||||
@@ -74,3 +74,15 @@ if (common.hasIntl) {
|
||||
(e) => e.code === 'ERR_INVALID_URL',
|
||||
'parsing http://\u00AD/bad.com/');
|
||||
}
|
||||
|
||||
{
|
||||
const badURLs = [
|
||||
'https://evil.com:.example.com',
|
||||
'git+ssh://git@github.com:npm/npm',
|
||||
];
|
||||
badURLs.forEach((badURL) => {
|
||||
assert.throws(() => { url.parse(badURL); },
|
||||
(e) => e.code === 'ERR_INVALID_URL',
|
||||
`parsing ${badURL}`);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user