crowdsecurity/crowdsec · critical
not enough entropy at random seed generation for JWT generat
Error message
not enough entropy at random seed generation for JWT generation
What it means
After rand.Read succeeds, randomSecret verifies it filled the whole 64-byte slice; a short read returns "not enough entropy at random seed generation for JWT generation". crypto/rand.Read is documented to always fill the buffer or error, so this branch is a defensive invariant check for a non-conforming or interrupted random source.
Source
Thrown at pkg/apiserver/middlewares/v1/jwt.go:261
func Unauthorized(c *gin.Context, code int, message string) {
c.JSON(code, gin.H{
"code": code,
"message": message,
})
}
func randomSecret() ([]byte, error) {
size := 64
secret := make([]byte, size)
n, err := rand.Read(secret)
if err != nil {
return nil, errors.New("unable to generate a new random seed for JWT generation")
}
if n != size {
return nil, errors.New("not enough entropy at random seed generation for JWT generation")
}
return secret, nil
}
func NewJWT(dbClient *database.Client) (*JWT, error) {
// Get secret from environment variable "SECRET"
var (
secret []byte
err error
)
// Please be aware that brute force HS256 is possible.
// PLEASE choose a STRONG secret
secretString := os.Getenv("CS_LAPI_SECRET")
secret = []byte(secretString)
switch l := len(secret); {View on GitHub (pinned to 909b515798)
Solutions
- Use the standard Go toolchain and unmodified crypto/rand (check go.mod for crypto/rand replaces)
- Set CS_LAPI_SECRET explicitly to bypass randomSecret entirely
- If on an exotic platform, provide a working random source to the runtime
- Retry startup; a transient short read will normally not recur
Example fix
// before: relying on runtime entropy on a limited platform // after export CS_LAPI_SECRET=$(head -c 48 /dev/urandom | base64 | tr -d '\n')
Defensive patterns
Strategy: retry
Validate before calling
// sanity-check the platform's random source before starting the service: head -c 64 /dev/urandom > /dev/null && echo "entropy ok"
Try / catch
jwt, err := NewJWT(dbClient)
if err != nil {
// transient entropy issue: retry once before failing
jwt, err = NewJWT(dbClient)
}
if err != nil { log.Fatalf("cannot start LAPI auth: %v", err) } Prevention
- Avoid vendoring/replacing crypto/rand in builds embedding crowdsec
- Set CS_LAPI_SECRET explicitly to bypass randomSecret on unusual platforms
- Use the standard Go toolchain and upstream crowdsec binaries
When it happens
Trigger: crypto/rand.Read returns n < 64 without an error — essentially never with the standard Go runtime, but possible with exotic platforms, fuzzing/instrumented builds, or a vendored replaced crypto/rand implementation.
Common situations: Custom Go toolchains or WASM/embedded builds with stubbed crypto/rand; test environments that replace the rand reader; effectively never in normal Linux/Windows/macOS deployments.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- unable to generate a new random seed for JWT generation
- generate random master secret: %w
- failed to generate nonce: %w
- generate challenge nonce: %w
- generate PoW prefix: %w
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/63a04d39ed3c55a7.
Report an issue: GitHub.