diff options
Diffstat (limited to 'dev-lang/go/files/go-1.25.3-ipv6-validation.patch')
| -rw-r--r-- | dev-lang/go/files/go-1.25.3-ipv6-validation.patch | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/dev-lang/go/files/go-1.25.3-ipv6-validation.patch b/dev-lang/go/files/go-1.25.3-ipv6-validation.patch new file mode 100644 index 000000000000..4f162b2b09a9 --- /dev/null +++ b/dev-lang/go/files/go-1.25.3-ipv6-validation.patch @@ -0,0 +1,86 @@ +From 83449b7e2f261c94ea46842012c0992a3a714ce5 Mon Sep 17 00:00:00 2001 +From: Roland Shoemaker <roland@golang.org> +Date: Wed, 08 Oct 2025 17:13:12 -0700 +Subject: [PATCH] [release-branch.go1.25] net/url: allow IP-literals with IPv4-mapped IPv6 addresses + +The security fix we applied in CL709857 was overly broad. It applied +rules from RFC 2732, which disallowed IPv4-mapped IPv6 addresses, but +these were later allowed in RFC 3986, which is the canonical URI syntax +RFC. + +Revert the portion of CL709857 which restricted IPv4-mapped addresses, +and update the related tests. + +Updates #75815 +Fixes #75832 + +Change-Id: I3192f2275ad5c386f5c15006a6716bdb5282919d +Reviewed-on: https://go-review.googlesource.com/c/go/+/710375 +LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> +Reviewed-by: Ethan Lee <ethanalee@google.com> +Auto-Submit: Roland Shoemaker <roland@golang.org> +(cherry picked from commit 9db7e30bb42eed9912f5e7e9e3959f3b38879d5b) +--- + +diff --git a/src/net/url/url.go b/src/net/url/url.go +index 40faa7c..1c50e06 100644 +--- a/src/net/url/url.go ++++ b/src/net/url/url.go +@@ -673,13 +673,13 @@ + + // Per RFC 3986, only a host identified by a valid + // IPv6 address can be enclosed by square brackets. +- // This excludes any IPv4 or IPv4-mapped addresses. ++ // This excludes any IPv4, but notably not IPv4-mapped addresses. + addr, err := netip.ParseAddr(unescapedHostname) + if err != nil { + return "", fmt.Errorf("invalid host: %w", err) + } +- if addr.Is4() || addr.Is4In6() { +- return "", errors.New("invalid IPv6 host") ++ if addr.Is4() { ++ return "", errors.New("invalid IP-literal") + } + return "[" + unescapedHostname + "]" + unescapedColonPort, nil + } else if i := strings.LastIndex(host, ":"); i != -1 { +diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go +index 3206558..6084fac 100644 +--- a/src/net/url/url_test.go ++++ b/src/net/url/url_test.go +@@ -726,7 +726,7 @@ + {"https://[2001:db8::1]/path", true}, // compressed IPv6 address with path + {"https://[fe80::1%25eth0]/path?query=1", true}, // link-local with zone, path, and query + +- {"https://[::ffff:192.0.2.1]", false}, ++ {"https://[::ffff:192.0.2.1]", true}, + {"https://[:1] ", false}, + {"https://[1:2:3:4:5:6:7:8:9]", false}, + {"https://[1::1::1]", false}, +@@ -1672,16 +1672,17 @@ + {"cache_object:foo/bar", true}, + {"cache_object/:foo/bar", false}, + +- {"http://[192.168.0.1]/", true}, // IPv4 in brackets +- {"http://[192.168.0.1]:8080/", true}, // IPv4 in brackets with port +- {"http://[::ffff:192.168.0.1]/", true}, // IPv4-mapped IPv6 in brackets +- {"http://[::ffff:192.168.0.1]:8080/", true}, // IPv4-mapped IPv6 in brackets with port +- {"http://[::ffff:c0a8:1]/", true}, // IPv4-mapped IPv6 in brackets (hex) +- {"http://[not-an-ip]/", true}, // invalid IP string in brackets +- {"http://[fe80::1%foo]/", true}, // invalid zone format in brackets +- {"http://[fe80::1", true}, // missing closing bracket +- {"http://fe80::1]/", true}, // missing opening bracket +- {"http://[test.com]/", true}, // domain name in brackets ++ {"http://[192.168.0.1]/", true}, // IPv4 in brackets ++ {"http://[192.168.0.1]:8080/", true}, // IPv4 in brackets with port ++ {"http://[::ffff:192.168.0.1]/", false}, // IPv4-mapped IPv6 in brackets ++ {"http://[::ffff:192.168.0.1000]/", true}, // Out of range IPv4-mapped IPv6 in brackets ++ {"http://[::ffff:192.168.0.1]:8080/", false}, // IPv4-mapped IPv6 in brackets with port ++ {"http://[::ffff:c0a8:1]/", false}, // IPv4-mapped IPv6 in brackets (hex) ++ {"http://[not-an-ip]/", true}, // invalid IP string in brackets ++ {"http://[fe80::1%foo]/", true}, // invalid zone format in brackets ++ {"http://[fe80::1", true}, // missing closing bracket ++ {"http://fe80::1]/", true}, // missing opening bracket ++ {"http://[test.com]/", true}, // domain name in brackets + } + for _, tt := range tests { + u, err := Parse(tt.in) |
