{"record":{"id":"7c5e09bf302b6d1e","repo":"vxcontrol/pentagi","slug":"token-validation-disabled-with-default-salt","errorCode":null,"errorMessage":"token validation disabled with default salt","messagePattern":"token validation disabled with default salt","errorType":"http","errorClass":null,"httpStatus":401,"severity":"warning","filePath":"backend/pkg/server/auth/auth_middleware.go","lineNumber":212,"sourceCode":"const PrivilegeAutomation = \"pentagi.automation\"\n\nfunc (p *AuthMiddleware) tryProtoTokenAuthentication(c *gin.Context) (authResult, error) {\n\tauthHeader := c.Request.Header.Get(\"Authorization\")\n\tif authHeader == \"\" {\n\t\treturn authResultSkip, errors.New(\"token required\")\n\t}\n\n\tif !strings.HasPrefix(authHeader, \"Bearer \") {\n\t\treturn authResultSkip, errors.New(\"bearer scheme must be used\")\n\t}\n\ttoken := authHeader[7:]\n\tif token == \"\" {\n\t\treturn authResultSkip, errors.New(\"token can't be empty\")\n\t}\n\n\t// skip validation if using default salt (for backward compatibility)\n\tif p.globalSalt == \"\" || p.globalSalt == \"salt\" {\n\t\treturn authResultSkip, errors.New(\"token validation disabled with default salt\")\n\t}\n\n\t// try to validate as API token first (new format with JWT signing key)\n\tapiClaims, apiErr := ValidateAPIToken(token, p.globalSalt)\n\tif apiErr != nil {\n\t\treturn authResultFail, errors.New(\"token is invalid\")\n\t}\n\n\t// check token status and get privileges through cache\n\tstatus, privileges, err := p.tokenCache.GetStatus(apiClaims.TokenID)\n\tif err != nil {\n\t\tif errors.Is(err, gorm.ErrRecordNotFound) {\n\t\t\treturn authResultFail, errors.New(\"token not found in database\")\n\t\t}\n\t\treturn authResultFail, fmt.Errorf(\"error checking token status: %w\", err)\n\t}\n\tif status != models.TokenStatusActive {\n\t\treturn authResultFail, errors.New(\"token has been revoked\")","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/server/auth/auth_middleware.go#L194-L230","documentation":"API-token authentication is disabled because the server is running with the default (unset or literal \"salt\") global salt. To stay backward compatible, the middleware refuses to validate API tokens in that mode and skips bearer auth rather than accepting tokens signed with a well-known key. This is a server configuration problem, not a client problem.","triggerScenarios":"Server env/config leaves the global salt empty or set to the literal \"salt\" (default) while a client sends `Authorization: Bearer <api-token>`; typically a fresh deployment where the salt env var was never customized.","commonSituations":"Deployed with .env.example defaults; docker-compose without the salt variable; intentional legacy mode where only cookie sessions work and API tokens are unsupported.","solutions":["Set a strong, unique global salt value in the server configuration (e.g. the salt/secret env var) and restart the backend.","Update docker-compose/.env to provide the non-default salt, then redeploy.","Until configured, authenticate via browser session cookie instead of API tokens.","Document the salt requirement in your deployment checklist to prevent recurrence."],"exampleFix":"# before (docker-compose.yml)\n# SALT not set -> defaults to \"salt\"\n\n# after\nenvironment:\n  - SALT=9f2c1d7e4b8a...  # long random value, never \"salt\"","handlingStrategy":"fallback","validationCode":"# on the server, before enabling API tokens:\nif [ -z \"$SALT\" ] || [ \"$SALT\" = \"salt\" ]; then\n  echo \"Refusing to start: SALT must be set to a strong non-default value\" >&2\n  exit 1\nfi","typeGuard":null,"tryCatchPattern":"try {\n  return await apiTokenAuth();\n} catch (e) {\n  if (is401(e) && /default salt/i.test(e.message)) {\n    logger.warn(\"API tokens disabled (default salt); falling back to session auth\");\n    return sessionAuth();\n  }\n  throw e;\n}","preventionTips":["Never deploy with example/default secret values; enforce a config lint.","Startup-validate that the salt is set and long/random.","Document that API-token auth requires a non-default salt."],"tags":["configuration","authentication","go","default-secret"],"backgroundTag":"default-secret-in-config","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}