{"record":{"id":"d29dcccf5c01fd3f","repo":"gofiber/fiber","slug":"csrf-token-invalid","errorCode":null,"errorMessage":"csrf: token invalid","messagePattern":"csrf: token invalid","errorType":"http","errorClass":null,"httpStatus":403,"severity":"warning","filePath":"middleware/csrf/csrf.go","lineNumber":25,"sourceCode":"\t\"slices\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"github.com/gofiber/utils/v2\"\n\tutilsstrings \"github.com/gofiber/utils/v2/strings\"\n\n\t\"github.com/gofiber/fiber/v3\"\n\t\"github.com/gofiber/fiber/v3/extractors\"\n\t\"github.com/gofiber/fiber/v3/internal/headerlookup\"\n\t\"github.com/gofiber/fiber/v3/internal/redact\"\n\t\"github.com/gofiber/fiber/v3/internal/schemehost\"\n\t\"github.com/gofiber/fiber/v3/middleware/logger\"\n)\n\nvar (\n\tErrTokenNotFound    = errors.New(\"csrf: token not found\")\n\tErrTokenInvalid     = errors.New(\"csrf: token invalid\")\n\tErrFetchSiteInvalid = errors.New(\"csrf: sec-fetch-site header invalid\")\n\tErrRefererNotFound  = errors.New(\"csrf: referer header missing\")\n\tErrRefererInvalid   = errors.New(\"csrf: referer header invalid\")\n\tErrRefererNoMatch   = errors.New(\"csrf: referer does not match host or trusted origins\")\n\tErrOriginInvalid    = errors.New(\"csrf: origin header invalid\")\n\tErrOriginNoMatch    = errors.New(\"csrf: origin does not match host or trusted origins\")\n\terrOriginNotFound   = errors.New(\"origin not supplied or is null\") // internal error, will not be returned to the user\n\tdummyValue          = []byte{'+'}                                  // dummyValue is a placeholder value stored in token storage. The actual token validation relies on the key, not this value.\n\n)\n\nvar registerLogContextTagsOnce sync.Once\n\n// Handler for CSRF middleware\ntype Handler struct {\n\tsessionManager *sessionManager\n\tstorageManager *storageManager\n\tconfig         Config","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/middleware/csrf/csrf.go#L7-L43","documentation":"Returned by middleware/csrf during Double Submit Cookie validation when the token extracted from the request (header/form/etc.) does not match the value of the CSRF cookie. The compare is constant-time; a mismatch means the submitted token was not bound to the browser's cookie, the canonical CSRF attack signal, so the request is rejected.","triggerScenarios":"The submitted token differs from the cookie value: client sent a stale token from an old cookie, two browser tabs holding different tokens, a token fabricated by an attacker who cannot read the cookie, or a custom Extractor that reads the same cookie (which the code warns provides no protection).","commonSituations":"User had multiple sessions/tabs and the cookie rotated; cookie was refreshed by a concurrent GET between read and submit; frontend cached an old token; a custom extractor pulls the token from the cookie itself, defeating the double-submit check.","solutions":["Re-fetch the token from a fresh GET before the mutation so token and cookie are in sync.","Confirm the extractor reads from a channel other than the CSRF cookie (header/form), as the source comment warns.","Avoid concurrent token-rotating requests in the same session, or handle this error by refreshing and retrying.","Make sure the cookie is actually present and not being blocked so the comparison has two valid sides."],"exampleFix":"// before: custom extractor reads the cookie (no protection)\nExtractor: csrf.CookieExtractor(CookieName)\n// after: read token from a header the client controls\nExtractor: csrf.HeaderExtractor(\"X-CSRF-Token\")","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if errors.Is(err, csrf.ErrTokenInvalid) {\n    // token/cookie mismatch: instruct client to refresh token, then retry\n    return c.Status(fiber.StatusForbidden).SendString(\"refresh csrf token\")\n}","preventionTips":["Do not write a custom extractor that reads the CSRF cookie as the token source.","Refresh the token before mutations if the session is long-lived.","Avoid concurrent token-rotating requests in one session."],"tags":["csrf","security","auth"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}