From 9a436085dac85bfdb55ef046a6b389ad1bc1c20a Mon Sep 17 00:00:00 2001 From: Jes Cok Date: Thu, 4 Sep 2025 01:58:19 +0800 Subject: [PATCH] net/url: don't permit a colon after the port Fixes #75223 Change-Id: Iaa12c7fc227ff33b8e97926d10967994a781720d --- src/net/url/url.go | 7 +++++++ src/net/url/url_test.go | 14 ++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/net/url/url.go b/src/net/url/url.go index 2a57659460373d..7021f343972ea2 100644 --- a/src/net/url/url.go +++ b/src/net/url/url.go @@ -661,6 +661,13 @@ func parseHost(host string) (string, error) { return host1 + host2 + host3, nil } } else if i := strings.LastIndex(host, ":"); i != -1 { + if j := strings.LastIndex(host[:i], ":"); j != -1 { // multiple colons + if k := strings.LastIndex(host[:j], ":"); k == -1 { // only one other colon + if port := host[j:i]; validOptionalPort(port) { // see issue #75223 + return "", fmt.Errorf("a colon after port %q is not allowed", port) + } + } + } colonPort := host[i:] if !validOptionalPort(colonPort) { return "", fmt.Errorf("invalid port %q after host", colonPort) diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go index 16e08b63c6d098..6c16f8fc057933 100644 --- a/src/net/url/url_test.go +++ b/src/net/url/url_test.go @@ -707,6 +707,13 @@ var parseRequestURLTests = []struct { // RFC 6874. {"http://[fe80::1%en0]/", false}, {"http://[fe80::1%en0]:8080/", false}, + + {"http://x:x:", true}, // malformed IPv6 but still accepted + {"http://x::", false}, // a colon after empty port is not allowed + {"http://x:1:", false}, // a colon after the port is not allowed + {"http://x:12:", false}, // a colon after the port is not allowed + {"http://x:123:", false}, // a colon after the port is not allowed + {"http://127.0.0.1:8080:", false}, // a colon after the port is not allowed } func TestParseRequestURI(t *testing.T) { @@ -1643,6 +1650,13 @@ func TestParseErrors(t *testing.T) { {"cache_object:foo", true}, {"cache_object:foo/bar", true}, {"cache_object/:foo/bar", false}, + + {"http://x:x:", false}, // malformed IPv6 but still accepted + {"http://x::", true}, // a colon after empty port is not allowed + {"http://x:1:", true}, // a colon after the port is not allowed + {"http://x:12:", true}, // a colon after the port is not allowed + {"http://x:123:", true}, // a colon after the port is not allowed + {"http://127.0.0.1:8080:", true}, // a colon after the port is not allowed } for _, tt := range tests { u, err := Parse(tt.in)