vxcontrol/pentagi · warning
token validation disabled with default salt
Error message
token validation disabled with default salt
What it means
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.
Source
Thrown at backend/pkg/server/auth/auth_middleware.go:212
const PrivilegeAutomation = "pentagi.automation"
func (p *AuthMiddleware) tryProtoTokenAuthentication(c *gin.Context) (authResult, error) {
authHeader := c.Request.Header.Get("Authorization")
if authHeader == "" {
return authResultSkip, errors.New("token required")
}
if !strings.HasPrefix(authHeader, "Bearer ") {
return authResultSkip, errors.New("bearer scheme must be used")
}
token := authHeader[7:]
if token == "" {
return authResultSkip, errors.New("token can't be empty")
}
// skip validation if using default salt (for backward compatibility)
if p.globalSalt == "" || p.globalSalt == "salt" {
return authResultSkip, errors.New("token validation disabled with default salt")
}
// try to validate as API token first (new format with JWT signing key)
apiClaims, apiErr := ValidateAPIToken(token, p.globalSalt)
if apiErr != nil {
return authResultFail, errors.New("token is invalid")
}
// check token status and get privileges through cache
status, privileges, err := p.tokenCache.GetStatus(apiClaims.TokenID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return authResultFail, errors.New("token not found in database")
}
return authResultFail, fmt.Errorf("error checking token status: %w", err)
}
if status != models.TokenStatusActive {
return authResultFail, errors.New("token has been revoked")View on GitHub (pinned to ea665308ba)
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.
Example fix
# before (docker-compose.yml) # SALT not set -> defaults to "salt" # after environment: - SALT=9f2c1d7e4b8a... # long random value, never "salt"
Defensive patterns
Strategy: fallback
Validate before calling
# on the server, before enabling API tokens: if [ -z "$SALT" ] || [ "$SALT" = "salt" ]; then echo "Refusing to start: SALT must be set to a strong non-default value" >&2 exit 1 fi
Try / catch
try {
return await apiTokenAuth();
} catch (e) {
if (is401(e) && /default salt/i.test(e.message)) {
logger.warn("API tokens disabled (default salt); falling back to session auth");
return sessionAuth();
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Deployed with .env.example defaults; docker-compose without the salt variable; intentional legacy mode where only cookie sessions work and API tokens are unsupported.
Related errors
- bearer scheme must be used
- token can't be empty
- token is invalid
- token not found in database
- token has been revoked
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/7c5e09bf302b6d1e.
Report an issue: GitHub.