gofiber/fiber · critical
CSRF: Chained extractor reads from the same cookie
Error message
CSRF: Chained extractor reads from the same cookie '${CookieName}' used for token storage. This completely defeats CSRF protection. What it means
Even when the top-level CSRF extractor is not the storage cookie, fiber walks the entire extractor tree via Extractor.Contains(...) and panics if ANY nested extractor in a chain (e.g. a Fallback, First, or Chain) reads from the storage cookie. This prevents hiding an insecure fallback behind a secure primary extractor. The predicate reuses isInsecureCookieExtractor against each node's Source/CookieName.
Solutions
- Audit every leaf of a composite extractor: no SourceCookie leaf may target cfg.CookieName.
- Use a distinct readable cookie name for any cookie-based fallback (separate from the HttpOnly storage cookie).
- Prefer a header/form primary and a non-storage-cookie fallback; remove cookie fallbacks that point at the storage cookie.
Example fix
// before
csrf.New(csrf.Config{
CookieName: "csrf",
Extractor: extractors.First(
extractors.Header("X-CSRF-Token"),
extractors.Cookie("csrf"), // insecure fallback
),
})
// after
csrf.New(csrf.Config{
CookieName: "csrf",
Extractor: extractors.First(
extractors.Header("X-CSRF-Token"),
extractors.Cookie("csrf_readable"), // different cookie
),
}) Defensive patterns
Strategy: validation
Validate before calling
// Walk the extractor tree and reject any leaf reading the storage cookie.
if cfg.Extractor.Contains(func(e extractors.Extractor) bool {
return e != nil && e.Source == extractors.SourceCookie && e.CookieName == cfg.CookieName
}) {
return errors.New("CSRF extractor chain must not read the storage cookie")
} Try / catch
defer func() {
if r := recover(); r != nil {
log.Fatalf("insecure CSRF extractor chain: %v", r)
}
}()
csrf.New(cfg) Prevention
- Audit every leaf of a composite extractor (Chain/First/Fallback) for the storage cookie name.
- Use a different, non-HttpOnly cookie name for any cookie-based fallback.
- Prefer header/form extractors; minimize cookie-based token reads.
When it happens
Trigger: csrf.New(csrf.Config{ CookieName: "csrf", Extractor: extractors.Chain(extractors.Header("X-CSRF-Token"), extractors.Cookie("csrf")) }) — a chain whose primary is safe but whose fallback reads the storage cookie. Also any composite (First, Fallback) that includes a SourceCookie node matching cfg.CookieName.
Common situations: Building a tolerant extractor that tries a header first and falls back to a cookie, accidentally naming the fallback cookie the same as the storage cookie; chaining third-party extractors that include a cookie reader; refactoring the extractor tree without re-checking every leaf.
Related errors
- CSRF: 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/9528266c7525c443.
Report an issue: GitHub.
Appendix: source
Thrown at middleware/csrf/config.go:197
}
// 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)
}
}
// isInsecureCookieExtractor checks if an extractor unsafely reads from the CSRF cookie
func isInsecureCookieExtractor(extractor extractors.Extractor, cookieName string) bool {
if extractor.Source == extractors.SourceCookie {
// Exact match - definitely insecure
if extractor.Key == cookieName {
return true
}
// Case-insensitive match - potentially confusing, warn but don't panicView on GitHub (pinned to a105acad6c)