{"id":"721026db84be21c1","repo":"gofiber/fiber","slug":"csrf-extractor-reads-from-the-same-cookie-cook","errorCode":null,"errorMessage":"CSRF: Extractor reads from the same cookie '${CookieName}' used for token storage. This completely defeats CSRF protection.","messagePattern":"CSRF: Extractor reads from the same cookie '(.+?)' used for token storage\\. This completely defeats CSRF protection\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"middleware/csrf/config.go","lineNumber":188,"sourceCode":"\t}\n\t// Check if Extractor is zero value (since it's a struct)\n\tif cfg.Extractor.Extract == nil {\n\t\tcfg.Extractor = ConfigDefault.Extractor\n\t}\n\t// Validate extractor security configurations\n\tvalidateExtractorSecurity(&cfg)\n\n\treturn cfg\n}\n\n// validateExtractorSecurity checks for insecure extractor configurations\nfunc validateExtractorSecurity(cfg *Config) {\n\tif cfg == nil {\n\t\treturn\n\t}\n\t// Check primary extractor\n\tif isInsecureCookieExtractor(cfg.Extractor, cfg.CookieName) {\n\t\tpanic(\"CSRF: Extractor reads from the same cookie '\" + cfg.CookieName +\n\t\t\t\"' used for token storage. This completely defeats CSRF protection.\")\n\t}\n\n\t// Check the full extractor tree so a nested chain cannot hide a fallback\n\t// that reads from the CSRF storage cookie.\n\tif cfg.Extractor.Contains(func(extractor extractors.Extractor) bool {\n\t\treturn isInsecureCookieExtractor(extractor, cfg.CookieName)\n\t}) {\n\t\tpanic(\"CSRF: Chained extractor reads from the same cookie '\" + cfg.CookieName +\n\t\t\t\"' used for token storage. This completely defeats CSRF protection.\")\n\t}\n\n\t// Additional security warnings (non-fatal)\n\tif cfg.Extractor.Source == extractors.SourceQuery || cfg.Extractor.Source == extractors.SourceParam {\n\t\tlog.Warnf(\"[CSRF WARNING] Using %v extractor - URLs may be logged\", cfg.Extractor.Source)\n\t}\n}\n","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/middleware/csrf/config.go#L170-L206","documentation":"The CSRF middleware stores its token in a cookie named CookieName (default \"csrf_\"); if you configure the token Extractor to read from that same cookie (SourceCookie with matching Key), the submitted token would always match the stored one, completely defeating CSRF protection. validateExtractorSecurity (csrf/config.go:182-205) detects this exact case on the primary extractor and panics at startup.","triggerScenarios":"Setting Extractor: extractors.FromCookie(\"csrf_\") while CookieName is also \"csrf_\" (or any matching name). The extractor struct's Source == SourceCookie and Key == CookieName.","commonSituations":"Building a double-submit cookie flow but accidentally pointing the extractor at the storage cookie instead of a separate readable token cookie; or copying a FromCookie example without realizing the default CookieName is \"csrf_\".","solutions":["Use the default header extractor (extractors.FromHeader(\"X-Csrf-Token\")) which reads the token from a request header the attacker cannot forge cross-site.","If you must read a cookie, use a different cookie name than CookieName and ensure that cookie is not the signed/authenticating one.","Switch SingleUseToken on for stronger protection, but keep the extractor source distinct from the storage cookie."],"exampleFix":"// before\ncsrf.New(csrf.Config{\n    CookieName: \"csrf_\",\n    Extractor:  extractors.FromCookie(\"csrf_\"),\n})\n\n// after\ncsrf.New(csrf.Config{\n    CookieName: \"csrf_\",\n    Extractor:  extractors.FromHeader(\"X-Csrf-Token\"), // default\n})","handlingStrategy":"validation","validationCode":"func validateCSRFExtractor(cfg csrf.Config) error {\n    if cfg.Extractor.Source == extractors.SourceCookie && cfg.Extractor.Key == cfg.CookieName {\n        return fmt.Errorf(\"extractor reads storage cookie %q\", cfg.CookieName)\n    }\n    return nil\n}\n\nif err := validateCSRFExtractor(cfg); err != nil { log.Fatal(err) }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default to a header extractor; only deviate after a security review.","Assert in a unit test that the extractor source differs from CookieName."],"tags":["csrf","security","cookie","extractor","misconfiguration","panic"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}