diff --git a/src/lib/isURL.js b/src/lib/isURL.js index 600a91dec..303e715c8 100644 --- a/src/lib/isURL.js +++ b/src/lib/isURL.js @@ -246,7 +246,11 @@ export default function isURL(url, options) { } if (options.host_whitelist) { - return checkHost(host, options.host_whitelist); + // `host` is '' for bracket-wrapped hosts like '[::1]'; the actual + // target lives in `ipv6`. Evaluate the whitelist against it too, + // otherwise whitelisted bracketed hosts are always rejected and an + // empty-matching whitelist regex accepts arbitrary bracketed hosts. + return checkHost(host || ipv6, options.host_whitelist); } if (host === '' && !options.require_host) { diff --git a/test/validators.test.js b/test/validators.test.js index 98d2a12ff..25a482cdd 100644 --- a/test/validators.test.js +++ b/test/validators.test.js @@ -879,6 +879,37 @@ describe('Validators', () => { }); }); + it('should evaluate the host whitelist against bracketed IPv6 hosts', () => { + test({ + validator: 'isURL', + args: [{ + host_whitelist: ['::1', /^2001:/], + }], + valid: [ + 'http://[::1]', + 'http://[::1]:8080', + 'http://[2001:db8::1]/', + ], + invalid: [ + 'http://example.com', + 'http://qux.com', + ], + }); + }); + + it('should not let an empty-matching whitelist regex accept bracketed garbage hosts', () => { + test({ + validator: 'isURL', + args: [{ + host_whitelist: [/^$/], + }], + valid: [], + invalid: [ + 'http://[not-an-ip]', + ], + }); + }); + it('should let users specify a host blacklist', () => { test({ validator: 'isURL',