{"record":{"id":"f7e9d614338d2b1f","repo":"crowdsecurity/crowdsec","slug":"unable-to-generate-a-new-random-seed-for-jwt-gener","errorCode":null,"errorMessage":"unable to generate a new random seed for JWT generation","messagePattern":"unable to generate a new random seed for JWT generation","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"pkg/apiserver/middlewares/v1/jwt.go","lineNumber":257,"sourceCode":"\nfunc Authorizator(data any, c *gin.Context) bool {\n\treturn true\n}\n\nfunc Unauthorized(c *gin.Context, code int, message string) {\n\tc.JSON(code, gin.H{\n\t\t\"code\":    code,\n\t\t\"message\": message,\n\t})\n}\n\nfunc randomSecret() ([]byte, error) {\n\tsize := 64\n\tsecret := make([]byte, size)\n\n\tn, err := rand.Read(secret)\n\tif err != nil {\n\t\treturn nil, errors.New(\"unable to generate a new random seed for JWT generation\")\n\t}\n\n\tif n != size {\n\t\treturn nil, errors.New(\"not enough entropy at random seed generation for JWT generation\")\n\t}\n\n\treturn secret, nil\n}\n\nfunc NewJWT(dbClient *database.Client) (*JWT, error) {\n\t// Get secret from environment variable \"SECRET\"\n\tvar (\n\t\tsecret []byte\n\t\terr    error\n\t)\n\n\t// Please be aware that brute force HS256 is possible.\n\t// PLEASE choose a STRONG secret","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/apiserver/middlewares/v1/jwt.go#L239-L275","documentation":"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.","triggerScenarios":"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.","commonSituations":"Highly restricted containers/jails blocking getrandom; corrupted or misconfigured minimal systems; embedded platforms with an unusable random device.","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"],"exampleFix":"// docker-compose: unblock getrandom\nsecurity_opt:\n  - seccomp:default.json  # or remove a custom profile blocking getrandom\n// or pre-set the secret\nenvironment:\n  - CS_LAPI_SECRET=aVeryLongRandomStringOfAtLeast64Characters...","handlingStrategy":"fallback","validationCode":"# ensure the secret env is set before launch so randomSecret is skipped:\ntest ${#CS_LAPI_SECRET} -ge 64 || echo \"CS_LAPI_SECRET short or unset; will need OS entropy\"","typeGuard":null,"tryCatchPattern":"jwt, err := NewJWT(dbClient)\nif err != nil {\n    log.Fatalf(\"cannot start LAPI auth: %v\", err) // fail fast with a clear message\n}","preventionTips":["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"],"tags":["crypto","entropy","startup","jwt"],"backgroundTag":"missing-env-var","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}