From e94545eec08427db9d59e32e4cac806c42efbf2b Mon Sep 17 00:00:00 2001 From: "s.v.churanov" Date: Mon, 26 Jan 2026 12:01:57 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20=D1=81orrect=20handling=20of=20multiple?= =?UTF-8?q?=20X-Forwarded-Host=20values=20Only=20the=20first=20host=20is?= =?UTF-8?q?=20considered=20according=20to=20RFC=207239?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: s.v.churanov --- pkg/requests/util/util.go | 6 ++++++ pkg/requests/util/util_test.go | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/pkg/requests/util/util.go b/pkg/requests/util/util.go index 290f8059..2dd7e97a 100644 --- a/pkg/requests/util/util.go +++ b/pkg/requests/util/util.go @@ -30,6 +30,12 @@ func GetRequestHost(req *http.Request) string { host := req.Header.Get(XForwardedHost) if !IsProxied(req) || host == "" { host = req.Host + } else { + // Handle multiple hosts in X-Forwarded-Host (comma-separated) + // Take only the first host as per RFC 7239 + if hosts := strings.Split(host, ","); len(hosts) > 0 { + host = strings.TrimSpace(hosts[0]) + } } return host } diff --git a/pkg/requests/util/util_test.go b/pkg/requests/util/util_test.go index ba72c66d..6ae30f47 100644 --- a/pkg/requests/util/util_test.go +++ b/pkg/requests/util/util_test.go @@ -59,6 +59,16 @@ var _ = Describe("Util Suite", func() { req.Header.Add("X-Forwarded-Host", "external.oauth2proxy.text") Expect(util.GetRequestHost(req)).To(Equal("external.oauth2proxy.text")) }) + + It("returns the first X-Forwarded-Host when multiple hosts are present", func() { + req.Header.Add("X-Forwarded-Host", "first.host,second.host,third.host") + Expect(util.GetRequestHost(req)).To(Equal("first.host")) + }) + + It("returns the first X-Forwarded-Host when multiple hosts are present with extra spaces", func() { + req.Header.Add("X-Forwarded-Host", " first.host , second.host , third.host ") + Expect(util.GetRequestHost(req)).To(Equal("first.host")) + }) }) })