From 78bfa2dc9684e40b6f34e91d0662cea08fe83d58 Mon Sep 17 00:00:00 2001 From: "Theo Gaige (Schneider Electric)" Date: Thu, 21 May 2026 12:09:42 +0200 Subject: [PATCH] go: patch CVE-2026-39825 Backport patch from [1] [1] https://go.dev/cl/770541 (From OE-Core rev: ae5b6a1b2bf80e73f18406153d314ff18a89a13f) Signed-off-by: Theo Gaige (Schneider Electric) Reviewed-by: Bruno Vernay Signed-off-by: Jeremy Rosen Signed-off-by: Paul Barker --- meta/recipes-devtools/go/go-1.22.12.inc | 1 + .../go/go/CVE-2026-39825.patch | 104 ++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 meta/recipes-devtools/go/go/CVE-2026-39825.patch diff --git a/meta/recipes-devtools/go/go-1.22.12.inc b/meta/recipes-devtools/go/go-1.22.12.inc index 002d443059..952c0e4638 100644 --- a/meta/recipes-devtools/go/go-1.22.12.inc +++ b/meta/recipes-devtools/go/go-1.22.12.inc @@ -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" diff --git a/meta/recipes-devtools/go/go/CVE-2026-39825.patch b/meta/recipes-devtools/go/go/CVE-2026-39825.patch new file mode 100644 index 0000000000..6082f5fc37 --- /dev/null +++ b/meta/recipes-devtools/go/go/CVE-2026-39825.patch @@ -0,0 +1,104 @@ +From 96b1a3f872971fc38d9f2c0ed4a3d1f3ceeb517f Mon Sep 17 00:00:00 2001 +From: Damien Neil +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 +Reviewed-by: Nicholas Husin +Auto-Submit: Damien Neil +LUCI-TryBot-Result: 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) +--- + 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 +