{"record":{"id":"b62530e10142117d","repo":"Tencent/WeKnora","slug":"failed-to-generate-jwt-secret-v","errorCode":null,"errorMessage":"failed to generate JWT secret: %v","messagePattern":"failed to generate JWT secret: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/application/service/user.go","lineNumber":89,"sourceCode":"\n// Machine-readable change-password failure reasons for HTTP details fields.\nconst (\n\tDetailInvalidOldPassword = \"invalid_old_password\"\n\tDetailPasswordPolicy     = \"password_policy\"\n\tDetailSamePassword       = \"same_password\"\n)\n\n// getJwtSecret retrieves the JWT secret from the environment, falling back to a securely generated random secret.\nfunc getJwtSecret() string {\n\tjwtSecretOnce.Do(func() {\n\t\tif envSecret := strings.TrimSpace(os.Getenv(\"JWT_SECRET\")); envSecret != \"\" {\n\t\t\tjwtSecret = envSecret\n\t\t\treturn\n\t\t}\n\n\t\trandomBytes := make([]byte, 32)\n\t\tif _, err := rand.Read(randomBytes); err != nil {\n\t\t\tpanic(fmt.Sprintf(\"failed to generate JWT secret: %v\", err))\n\t\t}\n\t\tjwtSecret = base64.StdEncoding.EncodeToString(randomBytes)\n\t})\n\n\treturn jwtSecret\n}\n\n// userService implements the UserService interface\ntype userService struct {\n\tuserRepo         interfaces.UserRepository\n\ttokenRepo        interfaces.AuthTokenRepository\n\ttenantService    interfaces.TenantService\n\tmemberService    interfaces.TenantMemberService\n\tconfig           *config.Config\n\tsystemSettingSvc interfaces.SystemSettingService\n}\n\n// NewUserService creates a new user service instance","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/user.go#L71-L107","documentation":"This panic occurs during lazy JWT secret initialization in the user service. After checking the JWT_SECRET env var, the code falls back to crypto/rand to generate 32 random bytes; if the OS entropy source fails, it panics with the wrapped error. It is an intentionally fatal startup failure because a JWT secret is mandatory for signing tokens.","triggerScenarios":"First call to the JWT-secret singleton when JWT_SECRET is unset/empty and rand.Read on the 32-byte slice returns an error (e.g. getrandom(2) syscall failure, exhausted or blocked entropy source, restricted seccomp/sandbox blocking getrandom).","commonSituations":"Containers with constrained /dev/urandom or seccomp profiles that block the getrandom syscall; exotic OSes or minimal kernels lacking getrandom; early-boot environments where the random device is not yet ready.","solutions":["Set the JWT_SECRET environment variable so the rand fallback is never taken","Fix the runtime environment: update the container/seccomp profile to allow the getrandom syscall, or ensure /dev/urandom is available","Retry process startup; rand.Read failure is usually transient on early boot","Replace with a deterministic secret source (key file/KMS) if the platform cannot supply entropy"],"exampleFix":"// before\njwtSecret = envSecret\n// after\nexport JWT_SECRET=$(openssl rand -base64 32)  # in deployment env, avoids rand fallback entirely","handlingStrategy":"fallback","validationCode":"secret := os.Getenv(\"JWT_SECRET\")\nif secret == \"\" {\n    if _, err := rand.Read(make([]byte, 32)); err != nil {\n        return nil, fmt.Errorf(\"entropy unavailable: %w\", err)\n    }\n}","typeGuard":"func hasJWTSecret() bool { return strings.TrimSpace(os.Getenv(\"JWT_SECRET\")) != \"\" }","tryCatchPattern":"func jwtSecretSafe() (s string, err error) {\n    defer func() { if r := recover(); r != nil { err = fmt.Errorf(\"jwt secret init panicked: %v\", r) } }()\n    return getJWTSecret(), nil\n}","preventionTips":["Always set JWT_SECRET in every deployment environment","Allow getrandom in container seccomp profiles","Provision secrets from a secret manager rather than runtime generation","Fail health checks early if entropy is unavailable"],"tags":["go","panic","crypto","jwt","entropy"],"backgroundTag":"crypto-rand-read-failure","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}