Summary
In v4.15.0, when checkSecFetchSiteRequest() returns (true, nil) (e.g., for direct URL navigation where Sec-Fetch-Site: none), the middleware calls return next(c) without setting the CSRF token in context. This breaks handlers that need the token to render forms.
Version
Reproduction
Handler that expects CSRF token in context:
func (h *handler) RegisterPage(c echo.Context) error {
csrfToken, ok := c.Get("csrf").(string)
if !ok {
return echo.NewHTTPError(http.StatusInternalServerError, "CSRF token not found")
}
// Render form with CSRF token...
}
Routes setup:
csrfMw := middleware.CSRFWithConfig(middleware.CSRFConfig{TokenLookup: "form:csrf"})
e.GET("/users/register", h.RegisterPage, csrfMw)
Test:
# Works in v4.14.0, fails in v4.15.0
curl -H "Sec-Fetch-Site: none" https://example.com/users/register
# Without header, both versions work
curl https://example.com/users/register
Expected Behavior
- GET /users/register with
Sec-Fetch-Site: none returns 200 with CSRF token in context and cookie set
- The form can be rendered with the token for subsequent POST
Actual Behavior (v4.15.0)
- GET /users/register with
Sec-Fetch-Site: none returns 500 "CSRF token not found"
- The token is never set in context because
checkSecFetchSiteRequest() returns early
Root Cause
In middleware/csrf.go around lines 164-167, when checkSecFetchSiteRequest() returns (true, nil):
allow, err := checkSecFetchSiteRequest(c)
if err != nil {
return err
}
if allow {
return next(c) // <-- Returns without setting token in context!
}
The middleware correctly validates the request is safe but then returns without:
- Generating/retrieving CSRF token
- Setting the cookie
- Setting the token in context
Suggested Fix
Even for "safe" requests per Sec-Fetch-Site validation, the middleware should still set the token in context and cookie:
if allow {
// Still need to set token for form rendering
token := ""
if k, err := c.Cookie(config.CookieName); err != nil {
token = randomString(config.TokenLength)
} else {
token = k.Value
}
// Set cookie and context even for "safe" requests
c.SetCookie(createCookie(config, token))
c.Set(config.ContextKey, token)
c.Response().Header().Add(echo.HeaderVary, echo.HeaderCookie)
return next(c)
}
Workaround
Downgrade to Echo v4.14.0 until this is fixed.
Impact
This breaks all server-rendered forms that use CSRF middleware when accessed via direct browser navigation (typing URL, bookmarks, clicking external links). The Sec-Fetch-Site: none header is automatically sent by all modern browsers in these scenarios.
Summary
In v4.15.0, when
checkSecFetchSiteRequest()returns(true, nil)(e.g., for direct URL navigation whereSec-Fetch-Site: none), the middleware callsreturn next(c)without setting the CSRF token in context. This breaks handlers that need the token to render forms.Version
Reproduction
Handler that expects CSRF token in context:
Routes setup:
Test:
Expected Behavior
Sec-Fetch-Site: nonereturns 200 with CSRF token in context and cookie setActual Behavior (v4.15.0)
Sec-Fetch-Site: nonereturns 500 "CSRF token not found"checkSecFetchSiteRequest()returns earlyRoot Cause
In
middleware/csrf.goaround lines 164-167, whencheckSecFetchSiteRequest()returns(true, nil):The middleware correctly validates the request is safe but then returns without:
Suggested Fix
Even for "safe" requests per Sec-Fetch-Site validation, the middleware should still set the token in context and cookie:
Workaround
Downgrade to Echo v4.14.0 until this is fixed.
Impact
This breaks all server-rendered forms that use CSRF middleware when accessed via direct browser navigation (typing URL, bookmarks, clicking external links). The
Sec-Fetch-Site: noneheader is automatically sent by all modern browsers in these scenarios.