crowdsecurity/crowdsec · error
master secret is %d bytes; minimum is %d
Error message
master secret is %d bytes; minimum is %d
What it means
NewChallengeRuntime validates the configured master_secret length and rejects anything shorter than minSecretBytes. The challenge cookie keyring derives keys from this secret, so a too-short secret is insecure and startup is aborted. Note: an empty/absent secret is auto-generated with a warning, but a present-but-short secret is a hard error.
Source
Thrown at pkg/appsec/challenge/challenge.go:410
}
logger := resolvedOpts.logger
if logger == nil {
logger = logging.SubLogger(log.StandardLogger(), "challenge", 0)
}
secret := resolvedOpts.masterSecret
if secret == nil {
var err error
secret, err = generateRandomSecret()
if err != nil {
return nil, err
}
logger.Warn("no master secret configured for the WAF challenge runtime; generated an ephemeral random secret. " +
"Distributed (multi-WAF) deployments MUST configure a shared master_secret in the appsec config; " +
"single-instance deployments will see outstanding challenge cookies invalidated on restart.")
} else if len(secret) < minSecretBytes {
return nil, fmt.Errorf("master secret is %d bytes; minimum is %d", len(secret), minSecretBytes)
}
rotationInterval := resolvedOpts.rotationInterval
if rotationInterval == 0 {
rotationInterval = keyringDefaultRotation
}
keys, err := NewKeyRing(secret, rotationInterval, resolvedOpts.maxLiveEpochs)
if err != nil {
return nil, fmt.Errorf("build challenge keyring: %w", err)
}
keys.logger = logger
cookieTTL := resolvedOpts.cookieTTL
if cookieTTL <= 0 {
cookieTTL = defaultCookieTTL
}
View on GitHub (pinned to 909b515798)
Solutions
- Set a master_secret of at least minSecretBytes bytes (32+ bytes recommended): openssl rand -base64 32.
- In multi-WAF deployments, share the same sufficient-length secret across all AppSec instances.
- Remove the master_secret field entirely to let the runtime generate an ephemeral one (single-instance only).
- Store the secret via your config management/secrets manager rather than typing a short one manually.
Example fix
// before (appsec config) master_secret: changeme // after generate with: openssl rand -base64 32 master_secret: kJ8fQ2xN7vR4tYw9zLm3Bc6aHd1pSg5XeU0iFo8kZrTn=
Defensive patterns
Strategy: validation
Validate before calling
// Go: validate secret length before writing config
const minSecretBytes = 32
secret, _ := base64.StdEncoding.DecodeString(cfg.MasterSecret)
if len(secret) < minSecretBytes {
return fmt.Errorf("master_secret too short: %d bytes, need >= %d", len(secret), minSecretBytes)
} Try / catch
cr, err := NewChallengeRuntime(...)
if err != nil {
if strings.Contains(err.Error(), "master secret is") {
return fmt.Errorf("appsec config: %w (generate with `openssl rand -base64 32`)", err)
}
return err
} Prevention
- Generate secrets with `openssl rand -base64 32` via your secrets manager
- Add config linting that checks master_secret length in CI
- Never use placeholder/example secrets in real deployments
When it happens
Trigger: Configuring the AppSec challenge runtime with a master_secret whose length is below minSecretBytes (e.g. 'secret', 'abc123').
Common situations: Hand-written appsec config with a short placeholder secret; operators shortening a secret to fit some other system; copy-pasted example config values.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- build challenge keyring: %w
- CS_LAPI_SECRET not strong enough
- token value for api.server.auto_register is too short (min 3
- cannot parse: %s
- invalid DSN %s for journalctl source, must start with journa
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/9da78911bf0271af.
Report an issue: GitHub.