From a67b393f2ce64040fde3c8d8f0320fa959813b70 Mon Sep 17 00:00:00 2001 From: Vishal Rana Date: Thu, 22 Oct 2026 15:46:08 -0700 Subject: [PATCH] fix(middleware): reject empty CSRF tokens in v4 Backport #3135 as defense in depth. Reject empty cookie or client tokens before constant-time comparison, retaining normal valid-token behavior. Co-authored-by: Harry Tran --- middleware/csrf.go | 3 +++ middleware/csrf_test.go | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/middleware/csrf.go b/middleware/csrf.go index d968c3880..60d316824 100644 --- a/middleware/csrf.go +++ b/middleware/csrf.go @@ -272,6 +272,9 @@ func (config CSRFConfig) ToMiddleware() (echo.MiddlewareFunc, error) { } func validateCSRFToken(token, clientToken string) bool { + if token == "" || clientToken == "" { + return false + } return subtle.ConstantTimeCompare([]byte(token), []byte(clientToken)) == 1 } diff --git a/middleware/csrf_test.go b/middleware/csrf_test.go index b7208e66e..b6712e228 100644 --- a/middleware/csrf_test.go +++ b/middleware/csrf_test.go @@ -275,6 +275,16 @@ func TestCSRFWithConfig(t *testing.T) { expectEmptyBody: true, expectErr: `code=403, message=invalid csrf token`, }, + { + name: "nok, POST empty cookie token + empty client token is blocked", + whenHeaders: map[string]string{ + echo.HeaderCookie: "_csrf=", + echo.HeaderXCSRFToken: "", + }, + whenMethod: http.MethodPost, + expectEmptyBody: true, + expectErr: `code=403, message=invalid csrf token`, + }, { name: "nok, invalid trusted origin in Config", givenConfig: &CSRFConfig{