{"record":{"id":"5683829ed6a994d3","repo":"gofiber/fiber","slug":"fiber-keyauth-scope-contains-invalid-token","errorCode":null,"errorMessage":"fiber: keyauth scope contains invalid token","messagePattern":"fiber: keyauth scope contains invalid token","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/keyauth/config.go","lineNumber":156,"sourceCode":"\t}\n\tif cfg.ErrorDescription != \"\" && cfg.Error == \"\" {\n\t\tpanic(\"fiber: keyauth error_description requires error\")\n\t}\n\tif cfg.ErrorURI != \"\" {\n\t\tif cfg.Error == \"\" {\n\t\t\tpanic(\"fiber: keyauth error_uri requires error\")\n\t\t}\n\t\tif u, err := url.Parse(cfg.ErrorURI); err != nil || !u.IsAbs() {\n\t\t\tpanic(\"fiber: keyauth error_uri must be absolute\")\n\t\t}\n\t}\n\tif cfg.Error == ErrorInsufficientScope {\n\t\tif cfg.Scope == \"\" {\n\t\t\tpanic(\"fiber: keyauth insufficient_scope requires scope\")\n\t\t}\n\t\tfor scope := range strings.SplitSeq(cfg.Scope, \" \") {\n\t\t\tif scope == \"\" || !isScopeToken(scope) {\n\t\t\t\tpanic(\"fiber: keyauth scope contains invalid token\")\n\t\t\t}\n\t\t}\n\t} else if cfg.Scope != \"\" {\n\t\tpanic(\"fiber: keyauth scope requires insufficient_scope error\")\n\t}\n\n\treturn cfg\n}\n\nfunc isScopeToken(s string) bool {\n\tfor i := 0; i < len(s); i++ {\n\t\tc := s[i]\n\t\tif c < 0x21 || c > 0x7e || c == '\"' || c == '\\\\' {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn s != \"\"\n}","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/middleware/keyauth/config.go#L138-L174","documentation":"When Error is insufficient_scope, keyauth splits Config.Scope on spaces and validates each token with isScopeToken, which permits printable ASCII (0x21–0x7e) except double-quote and backslash. Any token that is empty, contains a control char, a quote, or a backslash panics, because these would break the RFC 6750 scope parameter serialization in the WWW-Authenticate header (log injection / header-injection safe).","triggerScenarios":"Scope: \"read \\\"admin\\\"\" (contains quotes), \"read\\nwrite\" (newline, also a CRLF-injection risk), \"read  write\" (double space yields an empty token), or a scope containing a non-ASCII character.","commonSituations":"User-supplied scope names concatenated without sanitization; copy-pasting scopes from JSON where quotes were not stripped; trailing space producing an empty trailing token.","solutions":["Use simple alphanumeric scope tokens: \"read write admin\".","Trim and de-duplicate spaces before assigning Scope (e.g. strings.Join(strings.Fields(s), \" \")).","Reject scope names containing characters outside [A-Za-z0-9-_] at the source rather than relying on the middleware panic."],"exampleFix":"// before\napp.Use(keyauth.New(keyauth.Config{\n    Validator: v,\n    Error:     keyauth.ErrorInsufficientScope,\n    Scope:     \"read \\\"admin\\\"\",\n}))\n\n// after\napp.Use(keyauth.New(keyauth.Config{\n    Validator: v,\n    Error:     keyauth.ErrorInsufficientScope,\n    Scope:     \"read admin\",\n}))","handlingStrategy":"validation","validationCode":"func sanitizeScope(s string) (string, error) {\n    fields := strings.Fields(s) // collapses repeated spaces, drops empties\n    for _, f := range fields {\n        for i := 0; i < len(f); i++ {\n            c := f[i]\n            if c < 0x21 || c > 0x7e || c == '\"' || c == '\\\\' {\n                return \"\", fmt.Errorf(\"invalid scope token %q\", f)\n            }\n        }\n    }\n    return strings.Join(fields, \" \"), nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Restrict scope tokens to [A-Za-z0-9_-] at the source.","Normalize with strings.Fields to eliminate empty/whitespace tokens before assignment.","Never interpolate raw user input into Scope."],"tags":["keyauth","oauth","scope","rfc-6750","header-injection","config","auth","startup-panic"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}