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

  1. Use the standard Go toolchain and unmodified crypto/rand (check go.mod for crypto/rand replaces)
  2. Set CS_LAPI_SECRET explicitly to bypass randomSecret entirely
  3. If on an exotic platform, provide a working random source to the runtime
  4. 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

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


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/63a04d39ed3c55a7. Report an issue: GitHub.