{"record":{"id":"790a6228547d8bcd","repo":"Tencent/WeKnora","slug":"empty-jwk-modulus-or-exponent","errorCode":null,"errorMessage":"empty JWK modulus or exponent","messagePattern":"empty JWK modulus or exponent","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/service/user.go","lineNumber":1857,"sourceCode":"\t\treturn b, nil\n\t}\n\treturn base64.URLEncoding.DecodeString(value)\n}\n\nfunc (k oidcJWK) rsaPublicKey() (*rsa.PublicKey, error) {\n\tif !strings.EqualFold(k.Kty, \"RSA\") {\n\t\treturn nil, fmt.Errorf(\"unsupported JWK key type: %s\", k.Kty)\n\t}\n\tnBytes, err := decodeJWKBase64(k.N)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid JWK modulus: %w\", err)\n\t}\n\teBytes, err := decodeJWKBase64(k.E)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid JWK exponent: %w\", err)\n\t}\n\tif len(nBytes) == 0 || len(eBytes) == 0 {\n\t\treturn nil, errors.New(\"empty JWK modulus or exponent\")\n\t}\n\teInt := new(big.Int).SetBytes(eBytes)\n\tif !eInt.IsInt64() {\n\t\treturn nil, errors.New(\"invalid JWK exponent value\")\n\t}\n\te := int(eInt.Int64())\n\tif e <= 0 {\n\t\treturn nil, errors.New(\"invalid JWK exponent value\")\n\t}\n\treturn &rsa.PublicKey{N: new(big.Int).SetBytes(nBytes), E: e}, nil\n}\n\nfunc (jwks *oidcJWKS) rsaKeyForKid(kid string) (*rsa.PublicKey, error) {\n\tvar usable []oidcJWK\n\tfor _, k := range jwks.Keys {\n\t\tif k.Use != \"\" && !strings.EqualFold(k.Use, \"sig\") {\n\t\t\tcontinue\n\t\t}","sourceCodeStart":1839,"sourceCodeEnd":1875,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/user.go#L1839-L1875","documentation":"When converting a JWK (n = modulus, e = exponent) into an rsa.PublicKey, either field decoded to zero bytes. An RSA key cannot be built without both, so the function rejects the JWK. This indicates the JWKS entry is malformed or is not an actual RSA key.","triggerScenarios":"decodeJWKBase64 on k.N or k.E yields empty output — e.g. the JWKS key object is missing the 'n' or 'e' field, or they are empty strings.","commonSituations":"Provider publishes non-RSA keys (EC, OKP) in the same JWKS with missing n/e; truncated or hand-edited JWKS documents; a key entry that is only a partial stub.","solutions":["Inspect the JWKS document and confirm the matching key has non-empty 'n' and 'e' fields.","Filter JWKS entries by kty == \"RSA\" before parsing.","Refresh the JWKS from the authoritative jwks_uri in case a cached copy is corrupt.","Report/fix the provider if it publishes incomplete RSA keys."],"exampleFix":"// before: parsing every key in JWKS\nfor _, k := range jwks.Keys { buildRSAKey(k) }\n// after: only RSA keys\nfor _, k := range jwks.Keys {\n  if k.Kty == \"RSA\" && k.N != \"\" && k.E != \"\" { buildRSAKey(k) }\n}","handlingStrategy":"validation","validationCode":"func validRSAJWK(k jwk) bool {\n    n, errN := base64.RawURLEncoding.DecodeString(k.N)\n    e, errE := base64.RawURLEncoding.DecodeString(k.E)\n    return k.Kty == \"RSA\" && errN == nil && errE == nil && len(n) > 0 && len(e) > 0\n}","typeGuard":"func isRSAJWK(k jwk) bool { return k.Kty == \"RSA\" && k.N != \"\" && k.E != \"\" }","tryCatchPattern":null,"preventionTips":["Filter JWKS entries to kty == \"RSA\" before parsing.","Validate JWKS shape at cache-load time, not at verification time.","Re-fetch JWKS from discovery metadata rather than trusting hand-copied URIs."],"tags":["jwks","rsa","oidc","malformed-key"],"backgroundTag":"jwks-invalid-rsa-key","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}