{"record":{"id":"288f5924539b2ff8","repo":"github/github-mcp-server","slug":"w-authorization-header-is-badly-formatted","errorCode":null,"errorMessage":"%w: Authorization header is badly formatted","messagePattern":"%w: Authorization header is badly formatted","errorType":"validation","errorClass":"mark.ErrBadRequest","httpStatus":400,"severity":"error","filePath":"pkg/utils/token.go","lineNumber":34,"sourceCode":"\tTokenTypeUnknown TokenType = iota\n\tTokenTypePersonalAccessToken\n\tTokenTypeFineGrainedPersonalAccessToken\n\tTokenTypeOAuthAccessToken\n\tTokenTypeUserToServerGitHubAppToken\n\tTokenTypeServerToServerGitHubAppToken\n)\n\nvar supportedGitHubPrefixes = map[string]TokenType{\n\t\"ghp_\":        TokenTypePersonalAccessToken,            // Personal access token (classic)\n\t\"github_pat_\": TokenTypeFineGrainedPersonalAccessToken, // Fine-grained personal access token\n\t\"gho_\":        TokenTypeOAuthAccessToken,               // OAuth access token\n\t\"ghu_\":        TokenTypeUserToServerGitHubAppToken,     // User access token for a GitHub App\n\t\"ghs_\":        TokenTypeServerToServerGitHubAppToken,   // Installation access token for a GitHub App (a.k.a. server-to-server token)\n}\n\nvar (\n\tErrMissingAuthorizationHeader     = fmt.Errorf(\"%w: missing required Authorization header\", mark.ErrBadRequest)\n\tErrBadAuthorizationHeader         = fmt.Errorf(\"%w: Authorization header is badly formatted\", mark.ErrBadRequest)\n\tErrUnsupportedAuthorizationHeader = fmt.Errorf(\"%w: unsupported Authorization header\", mark.ErrBadRequest)\n)\n\n// oldPatternRegexp is the regular expression for the old pattern of the token.\n// Until 2021, GitHub API tokens did not have an identifiable prefix. They\n// were 40 characters long and only contained the characters a-f and 0-9.\nvar oldPatternRegexp = regexp.MustCompile(`\\A[a-f0-9]{40}\\z`)\n\n// ParseAuthorizationHeader parses the Authorization header from the HTTP request\nfunc ParseAuthorizationHeader(req *http.Request) (tokenType TokenType, token string, _ error) {\n\tauthHeader := req.Header.Get(httpheaders.AuthorizationHeader)\n\tif authHeader == \"\" {\n\t\treturn 0, \"\", ErrMissingAuthorizationHeader\n\t}\n\n\tswitch {\n\t// decrypt dotcom token and set it as token\n\tcase strings.HasPrefix(authHeader, \"GitHub-Bearer \"):","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/github/github-mcp-server/blob/0ea1f775a7c73eff1bd2e25904d01136756bbfe2/pkg/utils/token.go#L16-L52","documentation":"utils.ParseAuthorizationHeader found a header but the token - after optionally stripping 'Bearer ' (case-insensitive) - matches no supported GitHub format: none of the prefixes ghp_, github_pat_, gho_, ghu_, ghs_, and not the pre-2021 40-character lowercase-hex pattern (oldPatternRegexp). The middleware renders it as 400 'bad request: Authorization header is badly formatted'.","triggerScenarios":"Sending Authorization: Bearer my-token-123, a JWT, an unexpanded ${VAR} placeholder, another provider's token, or an empty value after 'Bearer ' - anything without a recognizable GitHub prefix.","commonSituations":"Copy-pasted example tokens never replaced; the wrong secret selected from a vault (AWS/OpenAI/GitLab key); hand-rolled test doubles issuing fake tokens; env interpolation failing so the literal placeholder is sent.","solutions":["Use a real GitHub token of a supported type: classic PAT (ghp_), fine-grained PAT (github_pat_), OAuth token (gho_), or GitHub App user/installation token (ghu_/ghs_)","Check for copy errors - prefixes are case-sensitive and a mangled 'Ghp_' or truncated token fails","For legacy 40-hex tokens confirm all 40 lowercase hex characters survived copying"],"exampleFix":"# before\nAuthorization: Bearer my-secret-token\n\n# after\nAuthorization: Bearer ghp_16C7e42F292c6912E7710c838347Ae178B4a","handlingStrategy":"validation","validationCode":"var gitHubTokenRe = regexp.MustCompile(`^(ghp_|github_pat_|gho_|ghu_|ghs_)[A-Za-z0-9_]+$|^[a-f0-9]{40}$`)\n\nfunc looksLikeGitHubToken(t string) bool { return gitHubTokenRe.MatchString(t) }\n\nif !looksLikeGitHubToken(token) {\n\treturn errors.New(\"refusing to send: not a recognizable GitHub token format\")\n}","typeGuard":"func isBadAuthHeader(err error) bool {\n\treturn errors.Is(err, utils.ErrBadAuthorizationHeader)\n}","tryCatchPattern":"if _, _, err := utils.ParseAuthorizationHeader(req); err != nil {\n\tif errors.Is(err, utils.ErrBadAuthorizationHeader) {\n\t\t// token format unrecognized: return 400 and tell the client to supply a real GitHub token\n\t}\n}","preventionTips":["Source tokens from GitHub UI or app flows - never hand-write them","Add a client-side prefix lint before shipping configuration","Distinguish 400 (bad token format) from 401 (missing header / challenge) in client handling"],"tags":["http","authentication","token","middleware","configuration"],"backgroundTag":null,"analyzedSha":"0ea1f775a7c73eff1bd2e25904d01136756bbfe2","analyzedAt":"2026-08-15T18:10:19.804Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}