crowdsecurity/crowdsec · critical
empty master secret
Error message
empty master secret
What it means
ParseConfiguredSecret parses the configured appsec master secret, accepting either a hex string or a raw passphrase, and requires a non-empty value yielding at least minSecretBytes. An empty configuration string cannot derive any key material, so it is rejected immediately with this error. It is called by BuildOptions when constructing the challenge runtime.
Source
Thrown at pkg/appsec/challenge/secret.go:38
// generateRandomSecret returns a fresh 32-byte secret suitable for use when
// no master_secret is configured. Single-instance deployments are fine with
// this; distributed deployments MUST configure a shared secret because each
// instance generates an independent random one here.
func generateRandomSecret() ([]byte, error) {
buf := make([]byte, 32)
if _, err := crand.Read(buf); err != nil {
return nil, fmt.Errorf("generate random master secret: %w", err)
}
return buf, nil
}
// ParseConfiguredSecret accepts a configured master secret as either a hex
// string (preferred — encodes raw bytes unambiguously) or a raw passphrase
// (fallback for human-edited configs). The result is at least minSecretBytes.
func ParseConfiguredSecret(value string) ([]byte, error) {
if value == "" {
return nil, errors.New("empty master secret")
}
// Hex form: even length, hex digits only.
if isHex(value) {
raw, err := hex.DecodeString(value)
if err == nil {
if len(raw) < minSecretBytes {
return nil, fmt.Errorf("hex master secret decodes to %d bytes; minimum is %d", len(raw), minSecretBytes)
}
return raw, nil
}
// Fall through to passphrase handling on hex parse failure — defensive.
}
if len(value) < minSecretBytes {
return nil, fmt.Errorf("passphrase master secret is %d bytes; minimum is %d", len(value), minSecretBytes)
}
View on GitHub (pinned to 909b515798)
Solutions
- Set a non-empty master secret in the appsec configuration (hex string preferred, e.g. `openssl rand -hex 32`).
- If using a passphrase, ensure it is at least minSecretBytes long.
- Check env-var interpolation isn't producing an empty value (e.g. ${SECRET} unset).
- Re-generate from the config template so the secret field is populated, then restart crowdsec.
Example fix
// before: empty value in appsec config
api:
appsec:
secret: ""
// after
api:
appsec:
secret: "6f1b...generated-hex..."
# or: openssl rand -hex 32 Defensive patterns
Strategy: validation
Validate before calling
// before calling BuildOptions/ParseConfiguredSecret
if secret == "" {
return errors.New("appsec master secret is not configured")
}
if _, err := challenge.ParseConfiguredSecret(secret); err != nil {
return fmt.Errorf("invalid master secret: %w", err)
} Try / catch
key, err := challenge.ParseConfiguredSecret(cfg.AppsecSecret)
if err != nil {
return fmt.Errorf("appsec secret config: %w", err) // includes "empty master secret"
} Prevention
- Generate and set the secret at install time (openssl rand -hex 32)
- Fail fast at startup with a clear message when the secret is empty
- Validate config templates so the secret field is never blank
- If secrets come from env, check interpolation resolved to a non-empty value
When it happens
Trigger: BuildOptions (or tests TestParseConfiguredSecret_*) passes "" as the configured secret value to ParseConfiguredSecret (secret.go:38).
Common situations: appsec config YAML has an empty secret/secret_file value; the config key was never set on a fresh install; an env var interpolated to empty at runtime; a config template left the field blank.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- invalid challenge master_secret: %w
- ref cannot be empty
- on_challenge hooks are only valid in-band, not under outofba
- on_challenge_submit hooks are only valid in-band, not under
- max_body_size must be a positive integer
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/159b3c6bb095a067.
Report an issue: GitHub.