From 8379878a478b29b9b894da2b4c67824660ea7f27 Mon Sep 17 00:00:00 2001 From: AdamMagued Date: Fri, 2 Oct 2026 06:14:34 +0300 Subject: [PATCH] fix(csrf): honor Secure(false) option for request URL scheme detection --- csrf.go | 2 +- csrf_test.go | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/csrf.go b/csrf.go index 5dda254..b67461d 100644 --- a/csrf.go +++ b/csrf.go @@ -269,7 +269,7 @@ func (cs *csrf) ServeHTTP(w http.ResponseWriter, r *http.Request) { requestURL := *r.URL // shallow clone requestURL.Scheme = "https" - if isPlaintext { + if isPlaintext || !cs.opts.Secure { requestURL.Scheme = "http" } if requestURL.Host == "" { diff --git a/csrf_test.go b/csrf_test.go index 0281680..4ef043b 100644 --- a/csrf_test.go +++ b/csrf_test.go @@ -542,3 +542,43 @@ func createRequest(method, path string, useTLS bool) *http.Request { } return r } + +// TestInsecureOriginSameOrigin tests that when csrf.Secure(false) is enabled, +// a POST request with Origin header "http://localhost:8080" and Host "localhost:8080" +// succeeds without ErrBadOrigin. +func TestInsecureOriginSameOrigin(t *testing.T) { + var token string + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + token = Token(r) + }) + mux.HandleFunc("/submit", testHandler) + + p := Protect(testKey, Secure(false))(mux) + + // Obtain a CSRF cookie via a GET request. + r := httptest.NewRequest("GET", "/", nil) + r.Host = "localhost:8080" + rr := httptest.NewRecorder() + p.ServeHTTP(rr, r) + + if rr.Code != http.StatusOK { + t.Fatalf("failed to obtain token: got %v want %v", rr.Code, http.StatusOK) + } + + // Issue POST with matching Origin header over HTTP. + r = httptest.NewRequest("POST", "/submit", nil) + r.Host = "localhost:8080" + r.Header.Set("Origin", "http://localhost:8080") + setCookie(rr, r) + r.Header.Set("X-CSRF-Token", token) + + rr = httptest.NewRecorder() + p.ServeHTTP(rr, r) + + if rr.Code != http.StatusOK { + t.Fatalf("middleware failed to accept same-origin HTTP request when Secure(false): got %v want %v", + rr.Code, http.StatusOK) + } +} +