crowdsecurity/crowdsec · error

invalid challenge master_secret: %w

Error message

invalid challenge master_secret: %w

What it means

BuildOptions translates the YAML challenge Config into runtime options. This error means the configured master_secret failed ParseConfiguredSecret validation: it is empty, is a hex string that decodes to fewer than 32 bytes, or is a passphrase shorter than 32 bytes. The runtime refuses to start with a weak or unparseable secret rather than silently padding it.

Source

Thrown at pkg/appsec/challenge/config.go:127

	if parent != nil {
		base = parent.Logger
	}

	var lvl log.Level
	if c != nil && c.LogLevel != nil {
		lvl = *c.LogLevel
	}

	opts := []Option{WithLogger(logging.SubLogger(base, "challenge", lvl))}

	if c == nil {
		return opts, nil
	}

	if c.MasterSecret != nil && *c.MasterSecret != "" {
		secret, err := ParseConfiguredSecret(*c.MasterSecret)
		if err != nil {
			return nil, fmt.Errorf("invalid challenge master_secret: %w", err)
		}
		opts = append(opts, WithMasterSecret(secret))
	}
	if c.KeyRotationInterval != nil {
		opts = append(opts, WithRotationInterval(*c.KeyRotationInterval))
	}
	if c.MaxLiveEpochs != nil && *c.MaxLiveEpochs > 0 {
		opts = append(opts, WithMaxLiveEpochs(*c.MaxLiveEpochs))
	}
	if c.CookieTTL != nil {
		opts = append(opts, WithCookieTTL(*c.CookieTTL))
	}
	if c.MaxCookieSize != nil && *c.MaxCookieSize > 0 {
		opts = append(opts, WithMaxCookieLen(*c.MaxCookieSize))
	}
	if c.CryptoObfuscationPoolSize != nil && *c.CryptoObfuscationPoolSize > 0 {
		opts = append(opts, WithCryptoObfuscationPoolSize(*c.CryptoObfuscationPoolSize))
	}

View on GitHub (pinned to 909b515798)

Solutions

  1. Generate a sufficiently long secret: `openssl rand -hex 32` (64 hex chars = 32 bytes) and set it as master_secret.
  2. If using a passphrase, ensure it is at least 32 characters long.
  3. Verify all fleet nodes use the exact same master_secret value.
  4. Check the wrapped error message: it states whether the hex decode length or passphrase length is below the 32-byte minimum.

Example fix

# before (too short: 32 hex chars = 16 bytes)
master_secret: a3f1b2c4d5e6f7089a1b2c3d4e5f6071
# after (64 hex chars = 32 bytes)
master_secret: $(openssl rand -hex 32)
Defensive patterns

Strategy: validation

Validate before calling

secret, err := challenge.ParseConfiguredSecret(cfg.MasterSecret)
if err != nil {
    return fmt.Errorf("master_secret: %w", err)
}

Try / catch

opts, err := challenge.BuildOptions(cfg, logger)
if err != nil {
    return fmt.Errorf("challenge configuration invalid: %w", err)
}

Prevention

When it happens

Trigger: Calling challenge.BuildOptions with a Config whose MasterSecret is non-empty but rejected by ParseConfiguredSecret — e.g. a short hex string, a short passphrase, or a value with invalid characters that still trips the hex-length check.

Common situations: Operators setting master_secret to a short human password in appsec config YAML; generating a hex secret with too few bytes (e.g. 16 random bytes = 32 hex chars, still under the 32-byte minimum); typos or truncation when copying the secret between fleet nodes.

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


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/4b19df08aa10826b. Report an issue: GitHub.