Node.js: url.parse() hostname spoofing via javascript: URIs

ID H1:395845
Type hackerone
Reporter bayotop
Modified 2020-01-15T09:00:13



Using url.parse() in security sensitive checks is dangerous as an arbitrary hostname can be spoofed via javascript: URIs.


The original url.parse() API is dangerous as it allows to spoof an arbitrary hostname via a javascript: URI:

```bash $ node -e 'console.log(require("url").parse("javAscript:alert(1);a=\\x27"))' Url { protocol: 'javascript:', slashes: null, auth: 'alert(1);a=\'', host: '', port: null, hostname: '', hash: null, search: null, query: null, pathname: '\'', path: '\'', href: 'javascript:alert(1)%3Ba%3D\'\'' }


Steps To Reproduce:

  1. node -e 'console.log(require("url").parse("javAscript:alert(1);a=\\x27"))'

After a quick look, I believe the issue stems from case-sensitive checks on lines 268 and 275

Additional notes:

I didn't set the severity as I have no idea how widely the "Legacy API" is still used and the actual impact is hugely context-based. For the sake of completeness, I found this issue when testing a real world app.

This also affects this npm package. The WHATWG API handles this particular case well.

In might be a good idea to mention in the documentation that URL parsing shouldn't be relied on in security relevant context. Exact string matching or similarly simple concepts should be always preferred.


This can be dangerous if used in security relevant access controls as follows:

js let parsedUrl = UrlHelper.parse(url); // url = javAscript:alert(1);a='@localhost/' if (parsedUrl.hostname === 'localhost') { // parsedUrl.hostname = localhost return true; // and do something like window.location = url }

Although being a bad practice, developers will write this code and will introduce bypassable access controls. Given that the bypass works only with javascript: URIs this will likely lead to XSS in most cases.