@@ -49,6 +49,7 @@ SRC_URI += "\
file://CVE-2026-39817.patch \
file://CVE-2026-39819.patch \
file://CVE-2026-39820.patch \
+ file://CVE-2026-39825.patch \
"
SRC_URI[main.sha256sum] = "012a7e1f37f362c0918c1dfa3334458ac2da1628c4b9cf4d9ca02db986e17d71"
new file mode 100644
@@ -0,0 +1,104 @@
+From 96b1a3f872971fc38d9f2c0ed4a3d1f3ceeb517f Mon Sep 17 00:00:00 2001
+From: Damien Neil <dneil@google.com>
+Date: Fri, 24 Apr 2026 14:10:47 -0700
+Subject: [PATCH] net/http/httputil: reencode queries with many parameters in
+ proxy
+
+When ReverseProxy forwards a request containing more than
+urlmaxqueryparams (GODEBUG) query parameters, reencode the
+outbound query parameters.
+
+Avoids potential smuggling of query parameters, where the
+sender sends many query parameters, the user's Rewrite hook
+fails to observe those parameters due to the limit being
+exceeded, and the request is forwarded with the full set
+of parameters.
+
+Fixes #78948
+Fixes CVE-2026-39825
+
+Change-Id: I691be7899c4b6208bf61f6b78dacfdf56a6a6964
+Reviewed-on: https://go-review.googlesource.com/c/go/+/770541
+Reviewed-by: Nicholas Husin <nsh@golang.org>
+Reviewed-by: Nicholas Husin <husin@google.com>
+Auto-Submit: Damien Neil <dneil@google.com>
+LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
+
+CVE: CVE-2026-39825
+Upstream-Status: Backport [https://github.com/golang/go/commit/6795bb331782b33691f772d30c810b4c3a317aeb]
+Signed-off-by: Theo Gaige (Schneider Electric) <tgaige.opensource@witekio.com>
+---
+ src/net/http/httputil/reverseproxy.go | 14 ++++++++++++++
+ src/net/http/httputil/reverseproxy_test.go | 6 ++++++
+ src/net/url/url.go | 1 +
+ 3 files changed, 21 insertions(+)
+
+diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go
+index 5c70f0d27b..37b0eab6b0 100644
+--- a/src/net/http/httputil/reverseproxy.go
++++ b/src/net/http/httputil/reverseproxy.go
+@@ -10,6 +10,7 @@ import (
+ "context"
+ "errors"
+ "fmt"
++ "internal/godebug"
+ "io"
+ "log"
+ "mime"
+@@ -797,11 +798,24 @@ func (c switchProtocolCopier) copyToBackend(errc chan<- error) {
+ errc <- err
+ }
+
++var urlmaxqueryparams = godebug.New("urlmaxqueryparams")
++
++// Keep this in sync with net/url.
++const defaultMaxParams = 10000
++
+ func cleanQueryParams(s string) string {
+ reencode := func(s string) string {
+ v, _ := url.ParseQuery(s)
+ return v.Encode()
+ }
++ if urlmaxqueryparams.Value() != "" {
++ // Always reencode when a non-default urlmaxqueryparams is set.
++ return reencode(s)
++ }
++ if numParams := strings.Count(s, "&") + 1; numParams > defaultMaxParams {
++ // Too many query parameters.
++ return reencode(s)
++ }
+ for i := 0; i < len(s); {
+ switch s[i] {
+ case ';':
+diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go
+index dd3330b615..deb1ab9ce2 100644
+--- a/src/net/http/httputil/reverseproxy_test.go
++++ b/src/net/http/httputil/reverseproxy_test.go
+@@ -1845,6 +1845,12 @@ func testReverseProxyQueryParameterSmuggling(t *testing.T, wantCleanQuery bool,
+ }, {
+ rawQuery: "a=1&a=%zz&b=3",
+ cleanQuery: "a=1&b=3",
++ }, {
++ rawQuery: "a=%zz",
++ cleanQuery: "",
++ }, {
++ rawQuery: strings.Repeat("a=1&", 10000) + "a=1",
++ cleanQuery: "",
+ }} {
+ res, err := frontend.Client().Get(frontend.URL + "?" + test.rawQuery)
+ if err != nil {
+diff --git a/src/net/url/url.go b/src/net/url/url.go
+index 5219e3c130..41f3bef1ee 100644
+--- a/src/net/url/url.go
++++ b/src/net/url/url.go
+@@ -961,6 +961,7 @@ func ParseQuery(query string) (Values, error) {
+
+ var urlmaxqueryparams = godebug.New("urlmaxqueryparams")
+
++// Keep this in sync with net/http/httputil.
+ const defaultMaxParams = 10000
+
+ func urlParamsWithinMax(params int) bool {
+--
+2.43.0
+