diff --git a/src/lib/isURL.js b/src/lib/isURL.js index 8ae971ed6..70725ce69 100644 --- a/src/lib/isURL.js +++ b/src/lib/isURL.js @@ -115,39 +115,46 @@ export default function isURL(url, options) { const starts_with_slashes = after_colon.slice(0, 2) === '//'; if (!starts_with_slashes) { - const first_slash_position = after_colon.indexOf('/'); - const before_slash = first_slash_position === -1 - ? after_colon - : after_colon.substring(0, first_slash_position); - const at_position = before_slash.indexOf('@'); - - if (at_position !== -1) { - const before_at = before_slash.substring(0, at_position); - const valid_auth_regex = /^[a-zA-Z0-9\-_.%:]*$/; - const is_valid_auth = valid_auth_regex.test(before_at); - - if (is_valid_auth) { - // This looks like authentication (e.g., user:password@host), not a protocol - if (options.require_protocol) { - return false; + const is_port_like = /^[0-9]+(?:[/?#]|$)/.test(after_colon); + if (is_port_like) { + if (options.require_protocol) { + return false; + } + } else { + const first_slash_position = after_colon.indexOf('/'); + const before_slash = first_slash_position === -1 + ? after_colon + : after_colon.substring(0, first_slash_position); + const at_position = before_slash.indexOf('@'); + + if (at_position !== -1) { + const before_at = before_slash.substring(0, at_position); + const valid_auth_regex = /^[a-zA-Z0-9\-_.%:]*$/; + const is_valid_auth = valid_auth_regex.test(before_at); + + if (is_valid_auth) { + // This looks like authentication (e.g., user:password@host), not a protocol + if (options.require_protocol) { + return false; + } + + // Don't consume the colon; let the auth parsing handle it later + } else { + // This looks like a malicious protocol (e.g., javascript:alert();@host) + url = cleanUpProtocol(potential_protocol); + + if (url === false) { + return false; + } } - - // Don't consume the colon; let the auth parsing handle it later } else { - // This looks like a malicious protocol (e.g., javascript:alert();@host) + // No @ symbol, this is definitely a protocol url = cleanUpProtocol(potential_protocol); if (url === false) { return false; } } - } else { - // No @ symbol, this is definitely a protocol - url = cleanUpProtocol(potential_protocol); - - if (url === false) { - return false; - } } } else { // Starts with '//', this is definitely a protocol like http:// diff --git a/test/validators.test.js b/test/validators.test.js index 5196c6fe9..9db1f1745 100644 --- a/test/validators.test.js +++ b/test/validators.test.js @@ -499,6 +499,7 @@ describe('Validators', () => { 'localhost', 'localhost:3000', 'service-name:8080', + 'my-3272-service:9000', 'https://localhost', 'http://localhost:3000', 'http://service-name:8080',