{"record":{"id":"95644171ab89b8e0","repo":"JuliusBrussee/caveman","slug":"caveman-auth-token-must-contain-no-spaces-or-control","errorCode":null,"errorMessage":"CAVEMAN_AUTH_TOKEN must contain no spaces or control characters","messagePattern":"CAVEMAN_AUTH_TOKEN must contain no spaces or control characters","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/internal/config/config.go","lineNumber":302,"sourceCode":"// minAuthTokenBytes is the floor for the inbound shared secret. The token is the\n// only gate in front of every configured provider credential once the proxy is\n// reachable off-host, so a short one is not a weaker deployment, it is an open one.\nconst minAuthTokenBytes = 16\n\n// validateAuthToken refuses a token that cannot survive one HTTP header value:\n// control bytes terminate the field, and a space would split scheme from value in\n// `Authorization: Bearer <token>`. The error never echoes the value — it is a\n// secret and this message reaches the proxy log.\nfunc validateAuthToken(token string) error {\n\tif token == \"\" {\n\t\treturn nil\n\t}\n\tif len(token) < minAuthTokenBytes {\n\t\treturn fmt.Errorf(\"CAVEMAN_AUTH_TOKEN must be at least %d bytes\", minAuthTokenBytes)\n\t}\n\tfor _, r := range token {\n\t\tif r == ' ' || r < 0x20 || r == 0x7f {\n\t\t\treturn fmt.Errorf(\"CAVEMAN_AUTH_TOKEN must contain no spaces or control characters\")\n\t\t}\n\t}\n\treturn nil\n}\n\n// validateListen keeps standalone's BYOK proxy local to one operator unless an\n// inbound credential gates it. Binding an empty, wildcard, or non-loopback host\n// would expose every configured provider credential to the network with no\n// inbound authentication; authenticated says CAVEMAN_AUTH_TOKEN is set, so\n// standalone.Auth rejects every request that does not present it and the wider\n// bind becomes a deliberate operator choice instead of an accident.\nfunc validateListen(listen string, authenticated bool) error {\n\thost, port, err := net.SplitHostPort(strings.TrimSpace(listen))\n\tif err != nil || port == \"\" {\n\t\treturn fmt.Errorf(\"listen address %q must be loopback host:port\", listen)\n\t}\n\tif strings.EqualFold(host, \"localhost\") {\n\t\treturn nil","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/proxy/internal/config/config.go#L284-L320","documentation":"Config validation error in the proxy's Load path: CAVEMAN_AUTH_TOKEN contains spaces or control characters. Control bytes would terminate the HTTP header field and a space would split scheme from value in 'Authorization: Bearer <token>'; the message deliberately never echoes the secret.","triggerScenarios":"Setting CAVEMAN_AUTH_TOKEN to a value with internal spaces (\"my secret token\"), trailing whitespace/newline (e.g. from `echo` without -n, or a CRLF line ending in .env), or an embedded tab.","commonSituations":"Pasting a secret with a trailing newline; generating tokens with a tool that appends a newline; quoting mistakes in shell assignment leaving literal spaces; Windows-edited config files with CRLF.","solutions":["Remove spaces and control characters from the token value (trim trailing newline/whitespace).","Regenerate with `openssl rand -hex 32`, which only produces hex digits.","Check the .env file for CRLF line endings (dos2unix) and remove surrounding quotes/whitespace."],"exampleFix":"// before\nexport CAVEMAN_AUTH_TOKEN=\"$(cat token.txt)\"        # file ends with newline\n// after\nexport CAVEMAN_AUTH_TOKEN=\"$(tr -d '[:space:]' < token.txt)\"","handlingStrategy":"validation","validationCode":"token := strings.TrimSpace(os.Getenv(\"CAVEMAN_AUTH_TOKEN\"))\nfor _, r := range token {\n    if r == ' ' || r < 0x20 || r == 0x7f {\n        return fmt.Errorf(\"CAVEMAN_AUTH_TOKEN contains space or control character at %q\", token)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Trim generated secrets before assigning them to env vars.","Save .env files with LF endings, not CRLF.","Use hex/base64 token generators that emit no whitespace."],"tags":["env-var","auth","whitespace"],"backgroundTag":"invalid-env-var-value","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}