{"record":{"id":"2b83fe6eea768ea5","repo":"OpenNHP/opennhp","slug":"jwt-signing-key-is-not-initialized","errorCode":null,"errorMessage":"JWT signing key is not initialized","messagePattern":"JWT signing key is not initialized","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"endpoints/server/kbs/attest/attest.go","lineNumber":129,"sourceCode":"\teBytes, err := base64.RawURLEncoding.DecodeString(pubkey.E)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid e: %w\", err)\n\t}\n\n\te := 0\n\tfor _, b := range eBytes {\n\t\te = e<<8 | int(b)\n\t}\n\n\treturn &rsa.PublicKey{\n\t\tN: new(big.Int).SetBytes(nBytes),\n\t\tE: e,\n\t}, nil\n}\n\nfunc generateJWT() (string, error) {\n\tif jwtSigningKey == nil {\n\t\treturn \"\", errors.New(\"JWT signing key is not initialized\")\n\t}\n\n\tclaims := CustomClaims{\n\t\tCosignAuthorized: true,\n\t\tRegisteredClaims: jwt.RegisteredClaims{\n\t\t\tIssuedAt:  jwt.NewNumericDate(time.Now()),\n\t\t\tExpiresAt: jwt.NewNumericDate(time.Now().Add(5 * time.Minute)),\n\t\t},\n\t}\n\n\ttoken := jwt.NewWithClaims(jwt.SigningMethodES256, claims)\n\n\tpublicKey := jwtSigningKey.PublicKey\n\ttoken.Header[\"jwk\"] = map[string]any{\n\t\t\"alg\": \"ES256\",\n\t\t\"crv\": \"P-256\",\n\t\t\"kty\": \"EC\",\n\t\t\"x\":   base64.RawURLEncoding.EncodeToString(publicKey.X.Bytes()),","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/endpoints/server/kbs/attest/attest.go#L111-L147","documentation":"generateJWT signs the KBS token with a package-level jwtSigningKey that must be initialized first (typically during startup, e.g. from ParseTeePubkey/generateJWT setup). If it is still nil when Attest() asks for a token, JWT creation is refused instead of panicking on a nil signing method.","triggerScenarios":"Attest() -> generateJWT runs before the key initialization step executed, or initialization failed silently earlier (e.g. key load error swallowed, wrong init order in tests or partial server startup).","commonSituations":"Unit tests calling generateJWT directly without setting jwtSigningKey; server started with a broken attestation config so init skipped; race where attestation request arrives during startup.","solutions":["Ensure the JWT signing key is generated/loaded during service init before Attest() is reachable","Check init logs for a failed key-load step and fix its root cause","Add the signing key setup to test fixtures when testing generateJWT","Guard startup so the KBS HTTP endpoints only register after key init succeeds"],"exampleFix":"// before (test)\ntoken, _ := generateJWT()\n// after\njwtSigningKey = mustGenerateSigningKey()\ntoken, _ := generateJWT()","handlingStrategy":"validation","validationCode":"if jwtSigningKey == nil {\n    return errors.New(\"generateJWT called before signing key init\")\n}\ntoken, err := generateJWT()","typeGuard":"func jwtReady() bool { return jwtSigningKey != nil }","tryCatchPattern":"token, err := generateJWT()\nif err != nil {\n    if err.Error() == \"JWT signing key is not initialized\" {\n        return fmt.Errorf(\"KBS not ready: %w\", err) // surface as 503 to callers\n    }\n    return err\n}","preventionTips":["Initialize the signing key in a single startup path before serving requests","Expose a readiness endpoint that reports jwtReady()","Add a unit test asserting generateJWT works after init"],"tags":["go","jwt","attestation","initialization"],"backgroundTag":"missing-credentials","analyzedSha":"6e04ca5ff03222a699c24205cd4bf8fee9af7ffe","analyzedAt":"2026-09-07T15:44:59.941Z","contentChangedAt":"2026-09-07T15:44:59.941Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}