crowdsecurity/crowdsec · critical
unable to generate a new random seed for JWT generation
Error message
unable to generate a new random seed for JWT generation
What it means
randomSecret generates the 64-byte HMAC seed used to sign LAPI JWTs via crypto/rand.Read. It returns "unable to generate a new random seed for JWT generation" when rand.Read returns an error, meaning the OS random source could not be read. Without this seed the API server cannot issue tokens, so NewJWT fails and startup aborts.
Source
Thrown at pkg/apiserver/middlewares/v1/jwt.go:257
func Authorizator(data any, c *gin.Context) bool {
return true
}
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 secretView on GitHub (pinned to 909b515798)
Solutions
- Set a strong CS_LAPI_SECRET (>=64 chars) so the random-seed path is never taken
- Verify getrandom(2)//dev/urandom is permitted for the crowdsec process (seccomp, apparmor, selinux)
- Test entropy availability: `head -c 64 /dev/urandom | xxd` on the host
- Restart the service after fixing the environment
Example fix
// docker-compose: unblock getrandom security_opt: - seccomp:default.json # or remove a custom profile blocking getrandom // or pre-set the secret environment: - CS_LAPI_SECRET=aVeryLongRandomStringOfAtLeast64Characters...
Defensive patterns
Strategy: fallback
Validate before calling
# ensure the secret env is set before launch so randomSecret is skipped:
test ${#CS_LAPI_SECRET} -ge 64 || echo "CS_LAPI_SECRET short or unset; will need OS entropy" Try / catch
jwt, err := NewJWT(dbClient)
if err != nil {
log.Fatalf("cannot start LAPI auth: %v", err) // fail fast with a clear message
} Prevention
- Set a strong CS_LAPI_SECRET in deployment configs so runtime entropy is not required
- Verify /dev/urandom access and getrandom(2) availability in your container image
- Test startup in staging with the same seccomp/apparmor profile as production
When it happens
Trigger: crowdsec starts with an empty/zero-length CS_LAPI_SECRET so it falls into the randomSecret branch, and crypto/rand.Read errors — e.g. getrandom(2) blocked by seccomp, or a broken entropy setup on the host.
Common situations: Highly restricted containers/jails blocking getrandom; corrupted or misconfigured minimal systems; embedded platforms with an unusable random device.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- not enough entropy at random seed generation for JWT generat
- 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/f7e9d614338d2b1f.
Report an issue: GitHub.