gofiber/fiber · critical
CSRF: Extractor reads from the same cookie
Error message
CSRF: Extractor reads from the same cookie '${CookieName}' used for token storage. This completely defeats CSRF protection. What it means
The CSRF middleware stores its token in cfg.CookieName and reads it from requests via cfg.Extractor. If the primary extractor's Source is extractors.SourceCookie and it reads the SAME cookie name used for token storage, the middleware would echo the stored token to any requester, completely defeating CSRF protection — so this configuration is rejected at startup. The check (isInsecureCookieExtractor) compares the extractor's CookieName against cfg.CookieName.
Solutions
- Read the CSRF token from a DIFFERENT source than the storage cookie — typically a header: extractors.Header("X-CSRF-Token"), or a form field, or a separate readable cookie with a different name.
- Keep the storage cookie (CookieName) HttpOnly and never point an extractor at it.
- If you need a double-submit cookie pattern, use two distinct cookie names: one HttpOnly storage cookie and one readable cookie for the extractor.
Example fix
// before
csrf.New(csrf.Config{
CookieName: "csrf_token",
Extractor: extractors.Cookie("csrf_token"),
})
// after
csrf.New(csrf.Config{
CookieName: "csrf_token", // HttpOnly storage
Extractor: extractors.Header("X-CSRF-Token"),
}) Defensive patterns
Strategy: validation
Validate before calling
// Ensure the extractor does not read from the storage cookie.
func extractorReadsStorageCookie(ex extractors.Extractor, storage string) bool {
return ex != nil && ex.Source == extractors.SourceCookie && ex.CookieName == storage
}
if extractorReadsStorageCookie(cfg.Extractor, cfg.CookieName) {
return errors.New("CSRF extractor must not read the storage cookie")
} Try / catch
defer func() {
if r := recover(); r != nil {
log.Fatalf("insecure CSRF extractor: %v", r)
}
}()
csrf.New(cfg) Prevention
- Read the CSRF token from a header or a separate readable cookie, never the HttpOnly storage cookie.
- Keep CookieName and the extractor target name distinct by convention (e.g. 'csrf' vs 'csrf_readable').
- In review, flag any SourceCookie extractor whose name equals CookieName.
When it happens
Trigger: csrf.New(csrf.Config{ CookieName: "csrf", Extractor: extractors.Cookie("csrf") }) — i.e. the extractor is told to pull the token from the very cookie the middleware uses to store it. Any SourceCookie extractor whose target name matches cfg.CookieName triggers the panic.
Common situations: Switching the extractor source to Cookie for an SPA that sends the token in a cookie, but forgetting the storage cookie must be HttpOnly/separate from the readable token; copy-paste where both fields get the same name; renaming the storage cookie without updating the extractor.
Related errors
- CSRF: Chained extractor reads from the same cookie
- [CSRF] Invalid origin format in configuration:
- [CORS] Configuration error: When 'AllowCredentials' is set…
- [CORS] Invalid origin format in configuration:
- fiber: encrypt cookie middleware requires key
AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11).
Data as JSON: /api/errors/721026db84be21c1.
Report an issue: GitHub.
Appendix: source
Thrown at middleware/csrf/config.go:188
}
// Check if Extractor is zero value (since it's a struct)
if cfg.Extractor.Extract == nil {
cfg.Extractor = ConfigDefault.Extractor
}
// Validate extractor security configurations
validateExtractorSecurity(&cfg)
return cfg
}
// validateExtractorSecurity checks for insecure extractor configurations
func validateExtractorSecurity(cfg *Config) {
if cfg == nil {
return
}
// Check primary extractor
if isInsecureCookieExtractor(cfg.Extractor, cfg.CookieName) {
panic("CSRF: Extractor reads from the same cookie '" + cfg.CookieName +
"' used for token storage. This completely defeats CSRF protection.")
}
// Check the full extractor tree so a nested chain cannot hide a fallback
// that reads from the CSRF storage cookie.
if cfg.Extractor.Contains(func(extractor extractors.Extractor) bool {
return isInsecureCookieExtractor(extractor, cfg.CookieName)
}) {
panic("CSRF: Chained extractor reads from the same cookie '" + cfg.CookieName +
"' used for token storage. This completely defeats CSRF protection.")
}
// Additional security warnings (non-fatal)
if cfg.Extractor.Source == extractors.SourceQuery || cfg.Extractor.Source == extractors.SourceParam {
log.Warnf("[CSRF WARNING] Using %v extractor - URLs may be logged", cfg.Extractor.Source)
}
}
View on GitHub (pinned to a105acad6c)