{"record":{"id":"6d28845421a4eb96","repo":"jwtk/jjwt","slug":"compact-jwe-string-represents-an-encrypted-key-bu","errorCode":null,"errorMessage":"Compact JWE string represents an encrypted key, but the key is empty.","messagePattern":"Compact JWE string represents an encrypted key, but the key is empty\\.","errorType":"exception","errorClass":"MalformedJwtException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java","lineNumber":510,"sourceCode":"        if (tokenized instanceof TokenizedJwe) {\n\n            TokenizedJwe tokenizedJwe = (TokenizedJwe) tokenized;\n            JweHeader jweHeader = Assert.stateIsInstance(JweHeader.class, header, \"Not a JweHeader. \");\n\n            // Ensure both an 'alg' and 'enc' header value exists and is supported before spending time/effort\n            // base64Url-decoding anything:\n            final AeadAlgorithm encAlg = this.encAlgs.apply(jweHeader);\n            Assert.stateNotNull(encAlg, \"JWE Encryption Algorithm cannot be null.\");\n            @SuppressWarnings(\"rawtypes\") final KeyAlgorithm keyAlg = this.keyAlgs.apply(jweHeader);\n            Assert.stateNotNull(keyAlg, \"JWE Key Algorithm cannot be null.\");\n\n            byte[] cekBytes = Bytes.EMPTY; //ignored unless using an encrypted key algorithm\n            CharSequence base64Url = tokenizedJwe.getEncryptedKey();\n            if (Strings.hasText(base64Url)) {\n                cekBytes = decode(base64Url, \"JWE encrypted key\");\n                if (Bytes.isEmpty(cekBytes)) {\n                    String msg = \"Compact JWE string represents an encrypted key, but the key is empty.\";\n                    throw new MalformedJwtException(msg);\n                }\n            }\n\n            base64Url = tokenizedJwe.getIv();\n            if (Strings.hasText(base64Url)) {\n                iv = decode(base64Url, \"JWE Initialization Vector\");\n            }\n            if (Bytes.isEmpty(iv)) {\n                String msg = \"Compact JWE strings must always contain an Initialization Vector.\";\n                throw new MalformedJwtException(msg);\n            }\n\n            // The AAD (Additional Authenticated Data) scheme for compact JWEs is to use the ASCII bytes of the\n            // raw base64url text as the AAD, and NOT the base64url-decoded bytes per\n            // https://www.rfc-editor.org/rfc/rfc7516.html#section-5.1, Step 14.\n            ByteBuffer buf = StandardCharsets.US_ASCII.encode(Strings.wrap(base64UrlHeader));\n            final byte[] aadBytes = new byte[buf.remaining()];\n            buf.get(aadBytes);","sourceCodeStart":492,"sourceCodeEnd":528,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java#L492-L528","documentation":"During compact JWE parsing, the parser decodes the base64url 'encrypted key' segment and requires it to decode to at least one byte. A present-but-empty encrypted key segment means the JWE structure is corrupt or was generated by a broken producer, so the library throws MalformedJwtException rather than attempting key-wrap decryption.","triggerScenarios":"Parsing a compact JWE whose fourth dot-separated component is non-empty base64url text that decodes to zero bytes (e.g. via JwtParser.parseClaimsJws/parse on a JWE string).","commonSituations":"Truncated or hand-edited JWE strings, buggy custom JWE builders that emit an empty key segment, round-tripping tokens through systems that mangle base64url padding.","solutions":["Regenerate the JWE with a correct producer (ensure KeyAlgorithm writes a non-empty encrypted key for the configured alg).","Verify the token wasn't truncated or altered in transit; compare against the original issuer output.","Inspect the 4th component of the compact string and confirm it is valid non-empty base64url for the key-encryption mode.","If using dir or direct CEK mode, expect no encrypted key segment at all — the string should have an empty 4th part, not whitespace or junk."],"exampleFix":"// before\nString jwe = header + \".\" + iv + \".\" + ciphertext + \".\" + \"\"; // empty encrypted key\n// after\nString jwe = header + \".\" + encryptedKey + \".\" + iv + \".\" + ciphertext + \".\" + tag;","handlingStrategy":"validation","validationCode":"String[] parts = jwe.split(\"\\\\.\", -1);\nif (parts.length == 5 && !parts[1].isEmpty()) {\n    byte[] ek = java.util.Base64.getUrlDecoder().decode(pad(parts[1]));\n    if (ek.length == 0) throw new IllegalArgumentException(\"empty JWE encrypted key\");\n}","typeGuard":null,"tryCatchPattern":"try { parser.parse(jwe); } catch (MalformedJwtException e) { log.warn(\"Corrupt JWE encrypted key: {}\", e.getMessage()); throw new TokenFormatException(e); }","preventionTips":["Never hand-assemble or hand-edit compact JWE strings.","Validate token structure (5 dot-separated base64url segments) at system boundaries.","Ensure token producers use JJWT's serializer rather than custom string building.","Guard against truncation by validating token length/checksums at transport layers."],"tags":["jwe","malformed-jwt","base64"],"backgroundTag":"invalid-argument-format","analyzedSha":"fb71496164c71442d08adec4571d9616ed5e1b8d","analyzedAt":"2026-09-09T00:33:09.982Z","contentChangedAt":"2026-09-09T00:33:09.982Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}