VYPR
Medium severityOSV Advisory· Published Apr 15, 2025· Updated Apr 15, 2026

CVE-2025-24358

CVE-2025-24358

Description

gorilla/csrf provides Cross Site Request Forgery (CSRF) prevention middleware for Go web applications & services. Prior to 1.7.2, gorilla/csrf does not validate the Origin header against an allowlist. Its executes its validation of the Referer header for cross-origin requests only when it believes the request is being served over TLS. It determines this by inspecting the r.URL.Scheme value. However, this value is never populated for "server" requests per the Go spec, and so this check does not run in practice. This vulnerability allows an attacker who has gained XSS on a subdomain or top level domain to perform authenticated form submissions against gorilla/csrf protected targets that share the same top level domain. This vulnerability is fixed in 1.7.2.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

gorilla/csrf prior to 1.7.2 does not validate Origin header and its Referer check for HTTPS never runs because r.URL.Scheme is empty for server requests, allowing CSRF from same top-level domain subdomains.

Vulnerability

gorilla/csrf is a CSRF protection middleware for Go web applications. Prior to version 1.7.2, it fails to validate the Origin header against an allowlist. Its intended Referer validation only executes for requests it believes are served over TLS, determined by inspecting r.URL.Scheme. However, in Go's net/http server, r.URL.Scheme is never populated for incoming requests, so the Referer check never actually runs [1][2]. This renders the CSRF protection ineffective for cross-origin requests.

Exploitation

An attacker who has gained XSS on any subdomain (or the top-level domain) of a site using gorilla/csrf can perform authenticated form submissions against protected endpoints. The attacker can exfiltrate the CSRF token and cookie from the target, then set a cookie with a broader path (e.g., /submit) so that it is sent by the browser when submitting a form from the attacker's origin. Since the Referer check is disabled, the malicious submission is accepted as legitimate [4].

Impact

Successful exploitation allows the attacker to perform state-changing actions (e.g., password change, financial transaction) on behalf of an authenticated victim, without proper origin validation. This qualifies as a Cross-Site Request Forgery vulnerability affecting the same top-level domain [2].

Mitigation

The vulnerability is fixed in gorilla/csrf 1.7.2. The fix adds validation of the Origin header against a trusted list and corrects the TLS detection logic by using request context to determine plaintext HTTP. Users should upgrade immediately. No workaround is available as the flawed check is integral to the middleware [3][4].

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/gorilla/csrfGo
< 1.7.31.7.3

Affected products

1

Patches

1
9dd6af1f6d30

Merge commit from fork

https://github.com/gorilla/csrfPatrick O'DohertyJan 23, 2025via ghsa
3 files changed · +307 131
  • csrf.go+75 14 modified
    @@ -1,10 +1,12 @@
     package csrf
     
     import (
    +	"context"
     	"errors"
     	"fmt"
     	"net/http"
     	"net/url"
    +	"slices"
     
     	"github.com/gorilla/securecookie"
     )
    @@ -22,6 +24,14 @@ const (
     	errorPrefix  string = "gorilla/csrf: "
     )
     
    +type contextKey string
    +
    +// PlaintextHTTPContextKey is the context key used to store whether the request
    +// is being served via plaintext HTTP. This is used to signal to the middleware
    +// that strict Referer checking should not be enforced as is done for HTTPS by
    +// default.
    +const PlaintextHTTPContextKey contextKey = "plaintext"
    +
     var (
     	// The name value used in form fields.
     	fieldName = tokenKey
    @@ -41,6 +51,9 @@ var (
     	// ErrNoReferer is returned when a HTTPS request provides an empty Referer
     	// header.
     	ErrNoReferer = errors.New("referer not supplied")
    +	// ErrBadOrigin is returned when the Origin header is present and is not a
    +	// trusted origin.
    +	ErrBadOrigin = errors.New("origin invalid")
     	// ErrBadReferer is returned when the scheme & host in the URL do not match
     	// the supplied Referer header.
     	ErrBadReferer = errors.New("referer invalid")
    @@ -242,10 +255,50 @@ func (cs *csrf) ServeHTTP(w http.ResponseWriter, r *http.Request) {
     	// HTTP methods not defined as idempotent ("safe") under RFC7231 require
     	// inspection.
     	if !contains(safeMethods, r.Method) {
    -		// Enforce an origin check for HTTPS connections. As per the Django CSRF
    -		// implementation (https://goo.gl/vKA7GE) the Referer header is almost
    -		// always present for same-domain HTTP requests.
    -		if r.URL.Scheme == "https" {
    +		var isPlaintext bool
    +		val := r.Context().Value(PlaintextHTTPContextKey)
    +		if val != nil {
    +			isPlaintext, _ = val.(bool)
    +		}
    +
    +		// take a copy of the request URL to avoid mutating the original
    +		// attached to the request.
    +		// set the scheme & host based on the request context as these are not
    +		// populated by default for server requests
    +		// ref: https://pkg.go.dev/net/http#Request
    +		requestURL := *r.URL // shallow clone
    +
    +		requestURL.Scheme = "https"
    +		if isPlaintext {
    +			requestURL.Scheme = "http"
    +		}
    +		if requestURL.Host == "" {
    +			requestURL.Host = r.Host
    +		}
    +
    +		// if we have an Origin header, check it against our allowlist
    +		origin := r.Header.Get("Origin")
    +		if origin != "" {
    +			parsedOrigin, err := url.Parse(origin)
    +			if err != nil {
    +				r = envError(r, ErrBadOrigin)
    +				cs.opts.ErrorHandler.ServeHTTP(w, r)
    +				return
    +			}
    +			if !sameOrigin(&requestURL, parsedOrigin) && !slices.Contains(cs.opts.TrustedOrigins, parsedOrigin.Host) {
    +				r = envError(r, ErrBadOrigin)
    +				cs.opts.ErrorHandler.ServeHTTP(w, r)
    +				return
    +			}
    +		}
    +
    +		// If we are serving via TLS and have no Origin header, prevent against
    +		// CSRF via HTTP machine in the middle attacks by enforcing strict
    +		// Referer origin checks. Consider an attacker who performs a
    +		// successful HTTP Machine-in-the-Middle attack and uses this to inject
    +		// a form and cause submission to our origin. We strictly disallow
    +		// cleartext HTTP origins and evaluate the domain against an allowlist.
    +		if origin == "" && !isPlaintext {
     			// Fetch the Referer value. Call the error handler if it's empty or
     			// otherwise fails to parse.
     			referer, err := url.Parse(r.Referer())
    @@ -255,18 +308,17 @@ func (cs *csrf) ServeHTTP(w http.ResponseWriter, r *http.Request) {
     				return
     			}
     
    -			valid := sameOrigin(r.URL, referer)
    -
    -			if !valid {
    -				for _, trustedOrigin := range cs.opts.TrustedOrigins {
    -					if referer.Host == trustedOrigin {
    -						valid = true
    -						break
    -					}
    -				}
    +			// disallow cleartext HTTP referers when serving via TLS
    +			if referer.Scheme == "http" {
    +				r = envError(r, ErrBadReferer)
    +				cs.opts.ErrorHandler.ServeHTTP(w, r)
    +				return
     			}
     
    -			if !valid {
    +			// If the request is being served via TLS and the Referer is not the
    +			// same origin, check the domain against our allowlist. We only
    +			// check when we have host information from the referer.
    +			if referer.Host != "" && referer.Host != r.Host && !slices.Contains(cs.opts.TrustedOrigins, referer.Host) {
     				r = envError(r, ErrBadReferer)
     				cs.opts.ErrorHandler.ServeHTTP(w, r)
     				return
    @@ -308,6 +360,15 @@ func (cs *csrf) ServeHTTP(w http.ResponseWriter, r *http.Request) {
     	contextClear(r)
     }
     
    +// PlaintextHTTPRequest accepts as input a http.Request and returns a new
    +// http.Request with the PlaintextHTTPContextKey set to true. This is used to
    +// signal to the CSRF middleware that the request is being served over plaintext
    +// HTTP and that Referer-based origin allow-listing checks should be skipped.
    +func PlaintextHTTPRequest(r *http.Request) *http.Request {
    +	ctx := context.WithValue(r.Context(), PlaintextHTTPContextKey, true)
    +	return r.WithContext(ctx)
    +}
    +
     // unauthorizedhandler sets a HTTP 403 Forbidden status and writes the
     // CSRF failure reason to the response.
     func unauthorizedHandler(w http.ResponseWriter, r *http.Request) {
    
  • csrf_test.go+224 101 modified
    @@ -1,6 +1,7 @@
     package csrf
     
     import (
    +	"fmt"
     	"net/http"
     	"net/http/httptest"
     	"strings"
    @@ -16,10 +17,7 @@ func TestProtect(t *testing.T) {
     	s := http.NewServeMux()
     	s.HandleFunc("/", testHandler)
     
    -	r, err := http.NewRequest("GET", "/", nil)
    -	if err != nil {
    -		t.Fatal(err)
    -	}
    +	r := createRequest("GET", "/", false)
     
     	rr := httptest.NewRecorder()
     	p := Protect(testKey)(s)
    @@ -46,10 +44,7 @@ func TestCookieOptions(t *testing.T) {
     	s := http.NewServeMux()
     	s.HandleFunc("/", testHandler)
     
    -	r, err := http.NewRequest("GET", "/", nil)
    -	if err != nil {
    -		t.Fatal(err)
    -	}
    +	r := createRequest("GET", "/", false)
     
     	rr := httptest.NewRecorder()
     	p := Protect(testKey, CookieName("nameoverride"), Secure(false), HttpOnly(false), Path("/pathoverride"), Domain("domainoverride"), MaxAge(173))(s)
    @@ -86,10 +81,7 @@ func TestMethods(t *testing.T) {
     
     	// Test idempontent ("safe") methods
     	for _, method := range safeMethods {
    -		r, err := http.NewRequest(method, "/", nil)
    -		if err != nil {
    -			t.Fatal(err)
    -		}
    +		r := createRequest(method, "/", false)
     
     		rr := httptest.NewRecorder()
     		p.ServeHTTP(rr, r)
    @@ -107,10 +99,7 @@ func TestMethods(t *testing.T) {
     	// Test non-idempotent methods (should return a 403 without a cookie set)
     	nonIdempotent := []string{"POST", "PUT", "DELETE", "PATCH"}
     	for _, method := range nonIdempotent {
    -		r, err := http.NewRequest(method, "/", nil)
    -		if err != nil {
    -			t.Fatal(err)
    -		}
    +		r := createRequest(method, "/", false)
     
     		rr := httptest.NewRecorder()
     		p.ServeHTTP(rr, r)
    @@ -133,10 +122,7 @@ func TestNoCookie(t *testing.T) {
     	p := Protect(testKey)(s)
     
     	// POST the token back in the header.
    -	r, err := http.NewRequest("POST", "http://www.gorillatoolkit.org/", nil)
    -	if err != nil {
    -		t.Fatal(err)
    -	}
    +	r := createRequest("POST", "/", false)
     
     	rr := httptest.NewRecorder()
     	p.ServeHTTP(rr, r)
    @@ -158,19 +144,13 @@ func TestBadCookie(t *testing.T) {
     	}))
     
     	// Obtain a CSRF cookie via a GET request.
    -	r, err := http.NewRequest("GET", "http://www.gorillatoolkit.org/", nil)
    -	if err != nil {
    -		t.Fatal(err)
    -	}
    +	r := createRequest("GET", "/", false)
     
     	rr := httptest.NewRecorder()
     	p.ServeHTTP(rr, r)
     
     	// POST the token back in the header.
    -	r, err = http.NewRequest("POST", "http://www.gorillatoolkit.org/", nil)
    -	if err != nil {
    -		t.Fatal(err)
    -	}
    +	r = createRequest("POST", "/", false)
     
     	// Replace the cookie prefix
     	badHeader := strings.Replace(cookieName+"=", rr.Header().Get("Set-Cookie"), "_badCookie", -1)
    @@ -193,10 +173,7 @@ func TestVaryHeader(t *testing.T) {
     	s.HandleFunc("/", testHandler)
     	p := Protect(testKey)(s)
     
    -	r, err := http.NewRequest("HEAD", "https://www.golang.org/", nil)
    -	if err != nil {
    -		t.Fatal(err)
    -	}
    +	r := createRequest("GET", "/", true)
     
     	rr := httptest.NewRecorder()
     	p.ServeHTTP(rr, r)
    @@ -211,16 +188,13 @@ func TestVaryHeader(t *testing.T) {
     	}
     }
     
    -// Requests with no Referer header should fail.
    +// TestNoReferer checks that HTTPS requests with no Referer header fail.
     func TestNoReferer(t *testing.T) {
     	s := http.NewServeMux()
     	s.HandleFunc("/", testHandler)
     	p := Protect(testKey)(s)
     
    -	r, err := http.NewRequest("POST", "https://golang.org/", nil)
    -	if err != nil {
    -		t.Fatal(err)
    -	}
    +	r := createRequest("POST", "https://golang.org/", true)
     
     	rr := httptest.NewRecorder()
     	p.ServeHTTP(rr, r)
    @@ -243,20 +217,12 @@ func TestBadReferer(t *testing.T) {
     	}))
     
     	// Obtain a CSRF cookie via a GET request.
    -	r, err := http.NewRequest("GET", "https://www.gorillatoolkit.org/", nil)
    -	if err != nil {
    -		t.Fatal(err)
    -	}
    -
    +	r := createRequest("GET", "/", true)
     	rr := httptest.NewRecorder()
     	p.ServeHTTP(rr, r)
     
     	// POST the token back in the header.
    -	r, err = http.NewRequest("POST", "https://www.gorillatoolkit.org/", nil)
    -	if err != nil {
    -		t.Fatal(err)
    -	}
    -
    +	r = createRequest("POST", "/", true)
     	setCookie(rr, r)
     	r.Header.Set("X-CSRF-Token", token)
     
    @@ -289,50 +255,47 @@ func TestTrustedReferer(t *testing.T) {
     	}
     
     	for _, item := range testTable {
    -		s := http.NewServeMux()
    +		t.Run(fmt.Sprintf("TrustedOrigin: %v", item.trustedOrigin), func(t *testing.T) {
     
    -		p := Protect(testKey, TrustedOrigins(item.trustedOrigin))(s)
    +			s := http.NewServeMux()
     
    -		var token string
    -		s.Handle("/", http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
    -			token = Token(r)
    -		}))
    +			p := Protect(testKey, TrustedOrigins(item.trustedOrigin))(s)
     
    -		// Obtain a CSRF cookie via a GET request.
    -		r, err := http.NewRequest("GET", "https://www.gorillatoolkit.org/", nil)
    -		if err != nil {
    -			t.Fatal(err)
    -		}
    +			var token string
    +			s.Handle("/", http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
    +				token = Token(r)
    +			}))
     
    -		rr := httptest.NewRecorder()
    -		p.ServeHTTP(rr, r)
    +			// Obtain a CSRF cookie via a GET request.
    +			r := createRequest("GET", "/", true)
     
    -		// POST the token back in the header.
    -		r, err = http.NewRequest("POST", "https://www.gorillatoolkit.org/", nil)
    -		if err != nil {
    -			t.Fatal(err)
    -		}
    +			rr := httptest.NewRecorder()
    +			p.ServeHTTP(rr, r)
     
    -		setCookie(rr, r)
    -		r.Header.Set("X-CSRF-Token", token)
    +			// POST the token back in the header.
    +			r = createRequest("POST", "/", true)
     
    -		// Set a non-matching Referer header.
    -		r.Header.Set("Referer", "http://golang.org/")
    +			setCookie(rr, r)
    +			r.Header.Set("X-CSRF-Token", token)
     
    -		rr = httptest.NewRecorder()
    -		p.ServeHTTP(rr, r)
    +			// Set a non-matching Referer header.
    +			r.Header.Set("Referer", "https://golang.org/")
     
    -		if item.shouldPass {
    -			if rr.Code != http.StatusOK {
    -				t.Fatalf("middleware failed to pass to the next handler: got %v want %v",
    -					rr.Code, http.StatusOK)
    -			}
    -		} else {
    -			if rr.Code != http.StatusForbidden {
    -				t.Fatalf("middleware failed reject a non-matching Referer header: got %v want %v",
    -					rr.Code, http.StatusForbidden)
    +			rr = httptest.NewRecorder()
    +			p.ServeHTTP(rr, r)
    +
    +			if item.shouldPass {
    +				if rr.Code != http.StatusOK {
    +					t.Fatalf("middleware failed to pass to the next handler: got %v want %v",
    +						rr.Code, http.StatusOK)
    +				}
    +			} else {
    +				if rr.Code != http.StatusForbidden {
    +					t.Fatalf("middleware failed reject a non-matching Referer header: got %v want %v",
    +						rr.Code, http.StatusForbidden)
    +				}
     			}
    -		}
    +		})
     	}
     }
     
    @@ -347,23 +310,16 @@ func TestWithReferer(t *testing.T) {
     	}))
     
     	// Obtain a CSRF cookie via a GET request.
    -	r, err := http.NewRequest("GET", "http://www.gorillatoolkit.org/", nil)
    -	if err != nil {
    -		t.Fatal(err)
    -	}
    -
    +	r := createRequest("GET", "/", true)
     	rr := httptest.NewRecorder()
     	p.ServeHTTP(rr, r)
     
     	// POST the token back in the header.
    -	r, err = http.NewRequest("POST", "http://www.gorillatoolkit.org/", nil)
    -	if err != nil {
    -		t.Fatal(err)
    -	}
    +	r = createRequest("POST", "/", true)
     
     	setCookie(rr, r)
     	r.Header.Set("X-CSRF-Token", token)
    -	r.Header.Set("Referer", "http://www.gorillatoolkit.org/")
    +	r.Header.Set("Referer", "https://www.gorillatoolkit.org/")
     
     	rr = httptest.NewRecorder()
     	p.ServeHTTP(rr, r)
    @@ -387,26 +343,19 @@ func TestNoTokenProvided(t *testing.T) {
     	s.Handle("/", http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
     		token = Token(r)
     	}))
    -
     	// Obtain a CSRF cookie via a GET request.
    -	r, err := http.NewRequest("GET", "http://www.gorillatoolkit.org/", nil)
    -	if err != nil {
    -		t.Fatal(err)
    -	}
    +	r := createRequest("GET", "/", true)
     
     	rr := httptest.NewRecorder()
     	p.ServeHTTP(rr, r)
     
     	// POST the token back in the header.
    -	r, err = http.NewRequest("POST", "http://www.gorillatoolkit.org/", nil)
    -	if err != nil {
    -		t.Fatal(err)
    -	}
    +	r = createRequest("POST", "/", true)
     
     	setCookie(rr, r)
     	// By accident we use the wrong header name for the token...
     	r.Header.Set("X-CSRF-nekot", token)
    -	r.Header.Set("Referer", "http://www.gorillatoolkit.org/")
    +	r.Header.Set("Referer", "https://www.gorillatoolkit.org/")
     
     	rr = httptest.NewRecorder()
     	p.ServeHTTP(rr, r)
    @@ -419,3 +368,177 @@ func TestNoTokenProvided(t *testing.T) {
     func setCookie(rr *httptest.ResponseRecorder, r *http.Request) {
     	r.Header.Set("Cookie", rr.Header().Get("Set-Cookie"))
     }
    +
    +func TestProtectScenarios(t *testing.T) {
    +	tests := []struct {
    +		name                 string
    +		safeMethod           bool
    +		originUntrusted      bool
    +		originHTTP           bool
    +		originTrusted        bool
    +		secureRequest        bool
    +		refererTrusted       bool
    +		refererUntrusted     bool
    +		refererHTTPDowngrade bool
    +		refererRelative      bool
    +		tokenValid           bool
    +		tokenInvalid         bool
    +		want                 bool
    +	}{
    +		{
    +			name:       "safe method pass",
    +			safeMethod: true,
    +			want:       true,
    +		},
    +		{
    +			name:       "cleartext POST with trusted origin & valid token pass",
    +			originHTTP: true,
    +			tokenValid: true,
    +			want:       true,
    +		},
    +		{
    +			name:            "cleartext POST with untrusted origin reject",
    +			originUntrusted: true,
    +			tokenValid:      true,
    +		},
    +		{
    +			name:       "cleartext POST with HTTP origin & invalid token reject",
    +			originHTTP: true,
    +		},
    +		{
    +			name:       "cleartext POST without origin with valid token pass",
    +			tokenValid: true,
    +			want:       true,
    +		},
    +		{
    +			name: "cleartext POST without origin with invalid token reject",
    +		},
    +		{
    +			name:          "TLS POST with HTTP origin & no referer & valid token reject",
    +			tokenValid:    true,
    +			secureRequest: true,
    +			originHTTP:    true,
    +		},
    +		{
    +			name:          "TLS POST without origin and without referer reject",
    +			secureRequest: true,
    +			tokenValid:    true,
    +		},
    +		{
    +			name:             "TLS POST without origin with untrusted referer reject",
    +			secureRequest:    true,
    +			refererUntrusted: true,
    +			tokenValid:       true,
    +		},
    +		{
    +			name:           "TLS POST without origin with trusted referer & valid token pass",
    +			secureRequest:  true,
    +			refererTrusted: true,
    +			tokenValid:     true,
    +			want:           true,
    +		},
    +		{
    +			name:                 "TLS POST without origin from _cleartext_ same domain referer with valid token reject",
    +			secureRequest:        true,
    +			refererHTTPDowngrade: true,
    +			tokenValid:           true,
    +		},
    +		{
    +			name:            "TLS POST without origin from relative referer with valid token pass",
    +			secureRequest:   true,
    +			refererRelative: true,
    +			tokenValid:      true,
    +			want:            true,
    +		},
    +		{
    +			name:            "TLS POST without origin from relative referer with invalid token reject",
    +			secureRequest:   true,
    +			refererRelative: true,
    +			tokenInvalid:    true,
    +		},
    +	}
    +
    +	for _, tt := range tests {
    +		t.Run(tt.name, func(t *testing.T) {
    +			var token string
    +			var flag bool
    +			mux := http.NewServeMux()
    +			mux.Handle("/", http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
    +				token = Token(r)
    +			}))
    +			mux.Handle("/submit", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    +				flag = true
    +			}))
    +			p := Protect(testKey)(mux)
    +
    +			// Obtain a CSRF cookie via a GET request.
    +			r := createRequest("GET", "/", tt.secureRequest)
    +			rr := httptest.NewRecorder()
    +			p.ServeHTTP(rr, r)
    +
    +			r = createRequest("POST", "/submit", tt.secureRequest)
    +			if tt.safeMethod {
    +				r = createRequest("GET", "/submit", tt.secureRequest)
    +			}
    +
    +			// Set the Origin header
    +			switch {
    +			case tt.originUntrusted:
    +				r.Header.Set("Origin", "http://www.untrusted-origin.org")
    +			case tt.originTrusted:
    +				r.Header.Set("Origin", "https://www.gorillatoolkit.org")
    +			case tt.originHTTP:
    +				r.Header.Set("Origin", "http://www.gorillatoolkit.org")
    +			}
    +
    +			// Set the Referer header
    +			switch {
    +			case tt.refererTrusted:
    +				p = Protect(testKey, TrustedOrigins([]string{"external-trusted-origin.test"}))(mux)
    +				r.Header.Set("Referer", "https://external-trusted-origin.test/foobar")
    +			case tt.refererUntrusted:
    +				r.Header.Set("Referer", "http://www.invalid-referer.org")
    +			case tt.refererHTTPDowngrade:
    +				r.Header.Set("Referer", "http://www.gorillatoolkit.org/foobar")
    +			case tt.refererRelative:
    +				r.Header.Set("Referer", "/foobar")
    +			}
    +
    +			// Set the CSRF token & associated cookie
    +			switch {
    +			case tt.tokenInvalid:
    +				setCookie(rr, r)
    +				r.Header.Set("X-CSRF-Token", "this-is-an-invalid-token")
    +			case tt.tokenValid:
    +				setCookie(rr, r)
    +				r.Header.Set("X-CSRF-Token", token)
    +			}
    +
    +			rr = httptest.NewRecorder()
    +			p.ServeHTTP(rr, r)
    +
    +			if tt.want && rr.Code != http.StatusOK {
    +				t.Fatalf("middleware failed to pass to the next handler: got %v want %v",
    +					rr.Code, http.StatusOK)
    +			}
    +
    +			if tt.want && !flag {
    +				t.Fatalf("middleware failed to pass to the next handler: got %v want %v",
    +					flag, true)
    +
    +			}
    +			if !tt.want && flag {
    +				t.Fatalf("middleware failed to reject the request: got %v want %v", flag, false)
    +			}
    +		})
    +	}
    +}
    +
    +func createRequest(method, path string, useTLS bool) *http.Request {
    +	r := httptest.NewRequest(method, path, nil)
    +	r.Host = "www.gorillatoolkit.org"
    +	if !useTLS {
    +		return PlaintextHTTPRequest(r)
    +	}
    +	return r
    +}
    
  • helpers_test.go+8 16 modified
    @@ -83,10 +83,7 @@ func TestMultipartFormToken(t *testing.T) {
     		}
     	}))
     
    -	r, err := http.NewRequest("GET", "/", nil)
    -	if err != nil {
    -		t.Fatal(err)
    -	}
    +	r := createRequest("GET", "/", true)
     
     	rr := httptest.NewRecorder()
     	p := Protect(testKey)(s)
    @@ -107,13 +104,13 @@ func TestMultipartFormToken(t *testing.T) {
     
     	mp.Close()
     
    -	r, err = http.NewRequest("POST", "http://www.gorillatoolkit.org/", &b)
    -	if err != nil {
    -		t.Fatal(err)
    -	}
    +	r = httptest.NewRequest("POST", "/", &b)
    +	r.Host = "www.gorillatoolkit.org"
     
     	// Add the multipart header.
     	r.Header.Set("Content-Type", mp.FormDataContentType())
    +	// Add Origin to pass the same-origin check.
    +	r.Header.Set("Origin", "https://www.gorillatoolkit.org")
     
     	// Send back the issued cookie.
     	setCookie(rr, r)
    @@ -246,10 +243,8 @@ func TestTemplateField(t *testing.T) {
     	}))
     
     	testFieldName := "custom_field_name"
    -	r, err := http.NewRequest("GET", "/", nil)
    -	if err != nil {
    -		t.Fatal(err)
    -	}
    +	r := createRequest("GET", "/", false)
    +	// r, err := http.NewRequest("GET", "/", nil)
     
     	rr := httptest.NewRecorder()
     	p := Protect(testKey, FieldName(testFieldName))(s)
    @@ -299,10 +294,7 @@ func TestUnsafeSkipCSRFCheck(t *testing.T) {
     		w.WriteHeader(teapot)
     	}))
     
    -	r, err := http.NewRequest("POST", "/", nil)
    -	if err != nil {
    -		t.Fatal(err)
    -	}
    +	r := createRequest("POST", "/", false)
     
     	// Must be used prior to the CSRF handler being invoked.
     	p := skipCheck(Protect(testKey)(s))
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.