crowdsecurity/crowdsec · error
failed to seal challenge cookie: %w
Error message
failed to seal challenge cookie: %w
What it means
After full validation, ValidateChallengeResponse seals an AppsecCookie under the master cookie key with an embedded not_after (cookieTTL) and the request's User-Agent. If sealCookieV0 fails, the error is wrapped as 'failed to seal challenge cookie' and no cookie can be issued even though the PoW itself succeeded.
Source
Thrown at pkg/appsec/challenge/challenge.go:725
"is_bot": fpData.FastBotDetection,
}).Debug("validated submission")
}
// Seal the difficulty the client actually proved (MAC-authenticated above),
// so the next request's re-challenge check compares against real work and an
// escalated per-request difficulty survives the cookie round-trip.
envelope := &pb.ChallengeCookie{
Fingerprint: fpData.ToProto(),
PowDifficulty: int32(clientDifficulty),
}
// Seal under the long-lived master cookie key. The embedded not_after makes
// the server validity window exactly c.cookieTTL (independent of key
// rotation); the browser Max-Age below matches so both expire together.
notAfter := time.Now().Add(c.cookieTTL).Unix()
cookieValue, err := sealCookieV0(envelope, c.keys.MasterCookieKey(), notAfter, 0, "", []byte(request.UserAgent()), c.maxCookieLen)
if err != nil {
return nil, FingerprintData{}, 0, fmt.Errorf("failed to seal challenge cookie: %w", err)
}
ck := cookie.NewAppsecCookie(ChallengeCookieName).HttpOnly().Path("/").SameSite(cookie.SameSiteLax).ExpiresIn(c.cookieTTL).Value(cookieValue)
if request.URL.Scheme == "https" {
ck = ck.Secure()
}
return ck, fpData, clientDifficulty, nil
}
// SealAllowlistCookie mints an allowlist-bypass cookie (no fingerprint, with
// the operator reason) so GrantChallengeCookie can let trusted bots skip the
// challenge UI while still hitting on_challenge rules via fingerprint.Allowlisted.
// not_after honors c.cookieTTL unless ttlOverride (>0) is given; reason is
// bounded by MaxAllowlistReasonLen (crypto.go).
func (c *ChallengeRuntime) SealAllowlistCookie(request *http.Request, reason string, ttlOverride *time.Duration) (*cookie.AppsecCookie, error) {
if c == nil {
return nil, errors.New("challenge runtime not initialized")View on GitHub (pinned to 909b515798)
Solutions
- Check the AppSec configuration for a valid, non-empty cookie secret / key material and restart.
- Review the wrapped error: if it reports size, increase maxCookieLen or shorten cookie contents.
- If it appeared after a key-rotation change, verify keys.MasterCookieKey() is initialized before validation runs.
- Report upstream with the wrapped error if it reproduces with default config — it indicates an internal invariant bug.
Example fix
# before: appsec config missing cookie secret
appsec:
challenge:
cookie_ttl: 30s
# after: provide key material
appsec:
challenge:
cookie_ttl: 30s
cookie_secret: <strong-random-secret> Defensive patterns
Strategy: try-catch
Validate before calling
// preflight in config loading: reject empty cookie key early
if len(keys.MasterCookieKey()) == 0 {
return errors.New("appsec: master cookie key is empty; cannot seal challenge cookies")
} Try / catch
cookie, fp, diff, err := rt.ValidateChallengeResponse(req, body)
if err != nil && strings.Contains(err.Error(), "seal challenge cookie") {
logger.WithError(err).Error("cookie sealing failed; check cookie key config and maxCookieLen")
http.Error(w, "internal error", http.StatusInternalServerError)
return
} Prevention
- Configure a strong, non-empty cookie secret before enabling challenges.
- Validate config at load time so a missing key fails fast.
- Keep maxCookieLen generous enough for typical User-Agent headers.
- Treat this as server-side: it never indicates an invalid client.
When it happens
Trigger: Calling ValidateChallengeResponse when sealCookieV0 returns an error — nil/invalid master cookie key, envelope serialization failure, cookie value exceeding maxCookieLen, or invalid inputs (empty key material after misconfiguration).
Common situations: Misconfigured or empty master cookie key in AppSec config; a User-Agent/cookie combination producing a sealed value longer than maxCookieLen (extremely long UA headers); internal key-rotation state corruption.
Related errors
- failed to seal allowlist cookie: %w
- cookie expired
- unknown cookie version
- unable to seal allowlist cookie: %w
- generate PoW salt: %w
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/f25d12be746041fd.
Report an issue: GitHub.