From e4cff3877397e0c40e228b2791fdf87153693a84 Mon Sep 17 00:00:00 2001 From: mkelvers Date: Wed, 22 Apr 2026 10:48:52 +0200 Subject: [PATCH] fix(csrf): handle X-Forwarded-Host and parse origin as URL --- pkg/middleware/csrf.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/pkg/middleware/csrf.go b/pkg/middleware/csrf.go index db7cc56..1afd853 100644 --- a/pkg/middleware/csrf.go +++ b/pkg/middleware/csrf.go @@ -16,7 +16,6 @@ func VerifyOrigin(next http.Handler) http.Handler { if origin == "" { referer := r.Header.Get("Referer") if referer == "" { - // If neither is present, and it's a POST/PUT/DELETE, reject it (strict policy) http.Error(w, "Missing Origin or Referer header", http.StatusForbidden) return } @@ -29,12 +28,21 @@ func VerifyOrigin(next http.Handler) http.Handler { origin = refURL.Scheme + "://" + refURL.Host } + originURL, err := url.Parse(origin) + if err != nil { + http.Error(w, "Invalid Origin header", http.StatusForbidden) + return + } + host := r.Host - // If origin doesn't match host (accounting for potential schema prefixes) + if forwardedHost := r.Header.Get("X-Forwarded-Host"); forwardedHost != "" { + host = forwardedHost + } + expectedHTTP := "http://" + host expectedHTTPS := "https://" + host - if origin != expectedHTTP && origin != expectedHTTPS { + if originURL.Scheme+"://"+originURL.Host != expectedHTTP && originURL.Scheme+"://"+originURL.Host != expectedHTTPS { http.Error(w, "Cross-Site Request Forgery (CSRF) origin mismatch", http.StatusForbidden) return }