@@ -177,7 +177,9 @@ function isIpv6Hostname(hostname) {
177177// as IPv6 by isIpv6Hostname above
178178//
179179// [1]: https://url.spec.whatwg.org/#forbidden-host-code-point
180- const forbiddenHostChars = / [ \t \n \r # % / : < > ? @ [ \\ \] ^ | ] / ;
180+ const forbiddenHostChars = / [ \0 \t \n \r # % / : < > ? @ [ \\ \] ^ | ] / ;
181+ // For IPv6, permit '[', ']', and ':'.
182+ const forbiddenHostCharsIpv6 = / [ \0 \t \n \r # % / < > ? @ \\ ^ | ] / ;
181183
182184Url . prototype . parse = function parse ( url , parseQueryString , slashesDenoteHost ) {
183185 validateString ( url , 'url' ) ;
@@ -400,27 +402,33 @@ Url.prototype.parse = function parse(url, parseQueryString, slashesDenoteHost) {
400402 this . hostname = this . hostname . toLowerCase ( ) ;
401403 }
402404
403- if ( ! ipv6Hostname && this . hostname !== '' ) {
404- // IDNA Support: Returns a punycoded representation of "domain".
405- // It only converts parts of the domain name that
406- // have non-ASCII characters, i.e. it doesn't matter if
407- // you call it with a domain that already is ASCII-only.
408-
409- // Use lenient mode (`true`) to try to support even non-compliant
410- // URLs.
411- this . hostname = toASCII ( this . hostname , true ) ;
412-
413- // Prevent two potential routes of hostname spoofing.
414- // 1. If this.hostname is empty, it must have become empty due to toASCII
415- // since we checked this.hostname above.
416- // 2. If any of forbiddenHostChars appears in this.hostname, it must have
417- // also gotten in due to toASCII. This is since getHostname would have
418- // filtered them out otherwise.
419- // Rather than trying to correct this by moving the non-host part into
420- // the pathname as we've done in getHostname, throw an exception to
421- // convey the severity of this issue.
422- if ( this . hostname === '' || forbiddenHostChars . test ( this . hostname ) ) {
423- throw new ERR_INVALID_URL ( url ) ;
405+ if ( this . hostname !== '' ) {
406+ if ( ipv6Hostname ) {
407+ if ( forbiddenHostCharsIpv6 . test ( this . hostname ) ) {
408+ throw new ERR_INVALID_URL ( url ) ;
409+ }
410+ } else {
411+ // IDNA Support: Returns a punycoded representation of "domain".
412+ // It only converts parts of the domain name that
413+ // have non-ASCII characters, i.e. it doesn't matter if
414+ // you call it with a domain that already is ASCII-only.
415+
416+ // Use lenient mode (`true`) to try to support even non-compliant
417+ // URLs.
418+ this . hostname = toASCII ( this . hostname , true ) ;
419+
420+ // Prevent two potential routes of hostname spoofing.
421+ // 1. If this.hostname is empty, it must have become empty due to toASCII
422+ // since we checked this.hostname above.
423+ // 2. If any of forbiddenHostChars appears in this.hostname, it must have
424+ // also gotten in due to toASCII. This is since getHostname would have
425+ // filtered them out otherwise.
426+ // Rather than trying to correct this by moving the non-host part into
427+ // the pathname as we've done in getHostname, throw an exception to
428+ // convey the severity of this issue.
429+ if ( this . hostname === '' || forbiddenHostChars . test ( this . hostname ) ) {
430+ throw new ERR_INVALID_URL ( url ) ;
431+ }
424432 }
425433 }
426434
0 commit comments