From: Ian Alexander Date: Wed, 28 Jan 2026 20:29:52 +0000 (-0500) Subject: [release-branch.go1.26] net/url: reject IPv6 literal not at start of host X-Git-Tag: go1.26.1~4 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=65c7d7a9fb3a9d1fbf1e702a211b8cc3a7bedb53;p=gostls13.git [release-branch.go1.26] net/url: reject IPv6 literal not at start of host This change rejects IPv6 literals that do not appear at the start of the host subcomponent of a URL. For example: http://example.com[::1] -> rejects http://[::1] -> accepts Thanks to Masaki Hara (https://github.com/qnighy) of Wantedly. Updates #77578 Fixes #77970 Fixes CVE-2026-25679 Change-Id: I7109031880758f7c1eb4eca513323328feace33c Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3400 Reviewed-by: Neal Patel Reviewed-by: Roland Shoemaker Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3622 Reviewed-on: https://go-review.googlesource.com/c/go/+/752080 Auto-Submit: Gopher Robot TryBot-Bypass: Gopher Robot Reviewed-by: Dmitri Shuralyov Reviewed-by: Cherry Mui --- diff --git a/src/net/url/url.go b/src/net/url/url.go index 202957a3a2..36d1820084 100644 --- a/src/net/url/url.go +++ b/src/net/url/url.go @@ -547,7 +547,9 @@ func parseAuthority(scheme, authority string) (user *Userinfo, host string, err // parseHost parses host as an authority without user // information. That is, as host[:port]. func parseHost(scheme, host string) (string, error) { - if openBracketIdx := strings.LastIndex(host, "["); openBracketIdx != -1 { + if openBracketIdx := strings.LastIndex(host, "["); openBracketIdx > 0 { + return "", errors.New("invalid IP-literal") + } else if openBracketIdx == 0 { // Parse an IP-Literal in RFC 3986 and RFC 6874. // E.g., "[fe80::1]", "[fe80::1%25en0]", "[fe80::1]:80". closeBracketIdx := strings.LastIndex(host, "]") diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go index d099353eb2..f0f3f97800 100644 --- a/src/net/url/url_test.go +++ b/src/net/url/url_test.go @@ -1756,6 +1756,12 @@ func TestParseErrors(t *testing.T) { {"http://[fe80::1", true}, // missing closing bracket {"http://fe80::1]/", true}, // missing opening bracket {"http://[test.com]/", true}, // domain name in brackets + {"http://example.com[::1]", true}, // IPv6 literal doesn't start with '[' + {"http://example.com[::1", true}, + {"http://[::1", true}, + {"http://.[::1]", true}, + {"http:// [::1]", true}, + {"hxxp://mathepqo[.]serveftp(.)com:9059", true}, } for _, tt := range tests { u, err := Parse(tt.in)