crowdsecurity/crowdsec · error
CS_LAPI_SECRET not strong enough
Error message
CS_LAPI_SECRET not strong enough
What it means
NewJWT validates CS_LAPI_SECRET, the HMAC secret used to sign LAPI JWTs. If the variable is set but shorter than 64 characters it returns "CS_LAPI_SECRET not strong enough" and the API server fails to start. The length floor prevents trivially brute-forceable token-signing keys.
Source
Thrown at pkg/apiserver/middlewares/v1/jwt.go:286
// Get secret from environment variable "SECRET"
var (
secret []byte
err error
)
// Please be aware that brute force HS256 is possible.
// PLEASE choose a STRONG secret
secretString := os.Getenv("CS_LAPI_SECRET")
secret = []byte(secretString)
switch l := len(secret); {
case l == 0:
secret, err = randomSecret()
if err != nil {
return &JWT{}, err
}
case l < 64:
return &JWT{}, errors.New("CS_LAPI_SECRET not strong enough")
}
jwtMiddleware := &JWT{
DbClient: dbClient,
TlsAuth: &TLSAuth{},
}
ret, err := jwt.New(&jwt.GinJWTMiddleware{
Realm: "Crowdsec API local",
Key: secret,
Timeout: time.Hour,
MaxRefresh: time.Hour,
IdentityKey: MachineIDKey,
PayloadFunc: PayloadFunc,
IdentityHandler: IdentityHandler,
Authenticator: jwtMiddleware.Authenticator,
Authorizator: Authorizator,
Unauthorized: Unauthorized,View on GitHub (pinned to 909b515798)
Solutions
- Generate a ≥64-character secret, e.g. `export CS_LAPI_SECRET=$(head -c 48 /dev/urandom | base64)`
- Ensure all LAPI clients (agents, bouncers' registration flows) get the same secret when you change it
- Fix the deployment template/script that produces the short value
- Alternatively unset CS_LAPI_SECRET (length 0) to let crowdsec generate a random secret itself
Example fix
// before CS_LAPI_SECRET=secret123 // after export CS_LAPI_SECRET=$(head -c 48 /dev/urandom | base64 | tr -d '\n')
Defensive patterns
Strategy: validation
Validate before calling
if v := os.Getenv("CS_LAPI_SECRET"); v != "" && len(v) < 64 {
return errors.New("CS_LAPI_SECRET must be at least 64 characters")
} Try / catch
jwt, err := NewJWT(dbClient)
if err != nil {
if strings.Contains(err.Error(), "not strong enough") {
log.Fatal("regenerate CS_LAPI_SECRET with: head -c 48 /dev/urandom | base64")
}
return err
} Prevention
- Generate secrets with `head -c 48 /dev/urandom | base64` (64+ chars after encoding)
- Fix deployment templates that default to short secrets like "changeme"
- Add a pre-start check in your entrypoint script that validates the secret length
- Rotate the secret across all LAPI clients whenever you change it
When it happens
Trigger: CS_LAPI_SECRET exported with a short value (0 < len < 64) before starting crowdsec/LAPI — e.g. a placeholder like "changeme", a truncated paste, or a deployment script writing a short default.
Common situations: Kubernetes/docker deployments templating the secret with a short default; ansible scripts generating too-short passwords; users following outdated docs that suggested short secrets.
Understand the failure class
Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.
Related errors
- master secret is %d bytes; minimum is %d
- build challenge keyring: %w
- missing lapi client credentials
- no appsec_config provided
- missing TLS key file
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/4569602ea9aaa60a.
Report an issue: GitHub.