crowdsecurity/crowdsec · critical
failed to generate nonce: %w
Error message
failed to generate nonce: %w
What it means
sealCookieV0 generates the random GCM nonce with crypto/rand.Read. This error means the OS CSPRNG failed, so the cookie cannot be sealed safely — without a fresh random nonce, AES-GCM nonce reuse would catastrophically break confidentiality and authenticity. The library fails closed.
Source
Thrown at pkg/appsec/challenge/crypto.go:145
gcm, err := cipher.NewGCM(block)
if err != nil {
return "", fmt.Errorf("failed to create GCM: %w", err)
}
// Reject an over-limit envelope before marshaling it.
maxPlaintext := maxCookieLen/4*3 - 1 - gcm.NonceSize() - gcm.Overhead()
if plaintextLen := cookiePlaintextFixedHeaderLen + len(reason) + proto.Size(envelope); plaintextLen > maxPlaintext {
return "", fmt.Errorf("%w: plaintext=%d > %d", ErrCookieTooLarge, plaintextLen, maxPlaintext)
}
envelopeBytes, err := proto.Marshal(envelope)
if err != nil {
return "", fmt.Errorf("failed to marshal challenge cookie proto: %w", err)
}
nonce := make([]byte, gcm.NonceSize())
if _, err := rand.Read(nonce); err != nil {
return "", fmt.Errorf("failed to generate nonce: %w", err)
}
// Build the plaintext: not_after_be8 || flags || reason_len_be || reason || envelope
plaintext := make([]byte, 0, cookiePlaintextFixedHeaderLen+len(reason)+len(envelopeBytes))
var notAfterBytes [8]byte
binary.BigEndian.PutUint64(notAfterBytes[:], uint64(notAfter))
plaintext = append(plaintext, notAfterBytes[:]...)
plaintext = append(plaintext, flags)
var reasonLenBytes [2]byte
binary.BigEndian.PutUint16(reasonLenBytes[:], uint16(len(reason)))
plaintext = append(plaintext, reasonLenBytes[:]...)
plaintext = append(plaintext, []byte(reason)...)
plaintext = append(plaintext, envelopeBytes...)
View on GitHub (pinned to 909b515798)
Solutions
- Inspect the wrapped OS error (errno) to identify the CSPRNG failure cause.
- Check the container/sandbox seccomp profile allows the getrandom syscall.
- Verify /dev/urandom is available and the host kernel is sane.
- Restart the process after fixing the environment; this is not retryable within the same call.
Example fix
// seccomp profile (docker/containerd): ensure getrandom is permitted
"syscalls": [
{"names": ["getrandom"], "action": "SCMP_ACT_ALLOW"}
] Defensive patterns
Strategy: retry
Try / catch
if err := errors.Is(err, randErr); err != nil {
// log the OS-level cause; fix sandbox/CSPRNG; restart process
return fmt.Errorf("cookie sealing unavailable, entropy failure: %w", err)
} Prevention
- Ensure seccomp/sandbox profiles allow the getrandom syscall.
- Monitor for crypto/rand failures in high-assurance environments.
- Avoid running with a broken or exhausted /dev/urandom in containers.
- Fail closed: never cache or reuse nonces to mask an entropy failure.
When it happens
Trigger: Calling sealCookieV0 (via SealAllowlistCookie or ValidateChallengeResponse) when crypto/rand.Read returns an error — e.g. getrandom(2) blocked by a seccomp/sandbox profile, fd exhaustion, or a broken /dev/urandom in the container.
Common situations: Containers or sandboxes with restrictive seccomp profiles blocking getrandom; severely resource-starved hosts; unusual kernels or restricted environments (some hardened container runtimes).
Related errors
- generate challenge nonce: %w
- generate PoW prefix: %w
- unable to generate a new random seed for JWT generation
- not enough entropy at random seed generation for JWT generat
- cookie expired
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/b1f1c466cbef9ab6.
Report an issue: GitHub.