{"record":{"id":"57ad7f898a11451e","repo":"jwtk/jjwt","slug":"the-jwt-header-references-compression-algorithm-57ad7f","errorCode":null,"errorMessage":"The JWT header references compression algorithm '%s', but payload decompression for Unprotected JWTs (those with an alg header value of 'none') or Unencoded JWSs (those with a b64 header value of false) that also rely on a SigningKeyResolver are disallowed by default to protect against [Denial of Service attacks](https://www.usenix.org/system/files/conference/usenixsecurity15/sec15-paper-pellegrino.pdf).  If you wish to enable Unsecure JWS or Unencoded JWS payload decompression, call the JwtParserBuilder.unsecuredDecompression() method, but please read the security considerations covered in that method's JavaDoc before doing so.","messagePattern":"The JWT header references compression algorithm '%s', but payload decompression for Unprotected JWTs \\(those with an alg header value of 'none'\\) or Unencoded JWSs \\(those with a b64 header value of false\\) that also rely on a SigningKeyResolver are disallowed by default to protect against \\[Denial of Service attacks\\]\\(https://www\\.usenix\\.org/system/files/conference/usenixsecurity15/sec15-paper-pellegrino\\.pdf\\)\\.  If you wish to enable Unsecure JWS or Unencoded JWS payload decompression, call the JwtParserBuilder\\.unsecuredDecompression\\(\\) method, but please read the security considerations covered in that method's JavaDoc before doing so\\.","errorType":"exception","errorClass":"UnsupportedJwtException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java","lineNumber":589,"sourceCode":"            integrityVerified = true; // AEAD performs integrity verification, so no exception = verified\n\n        } else if (hasDigest && this.signingKeyResolver == null) { //TODO: for 1.0, remove the == null check\n            // not using a signing key resolver, so we can verify the signature before reading the payload, which is\n            // always safer:\n            JwsHeader jwsHeader = Assert.stateIsInstance(JwsHeader.class, header, \"Not a JwsHeader. \");\n            digest = verifySignature(tokenized, jwsHeader, alg, new LocatingKeyResolver(this.keyLocator), null, payload);\n            integrityVerified = true; // no exception means signature verified\n        }\n\n        final CompressionAlgorithm compressionAlgorithm = zipAlgs.apply(header);\n        if (compressionAlgorithm != null) {\n            if (!integrityVerified) {\n                if (!payloadBase64UrlEncoded) {\n                    String msg = String.format(B64_DECOMPRESSION_MSG, compressionAlgorithm.getId());\n                    throw new UnsupportedJwtException(msg);\n                } else if (!unsecuredDecompression) {\n                    String msg = String.format(UNPROTECTED_DECOMPRESSION_MSG, compressionAlgorithm.getId());\n                    throw new UnsupportedJwtException(msg);\n                }\n            }\n            payload = payload.decompress(compressionAlgorithm);\n        }\n\n        Claims claims = null;\n        byte[] payloadBytes = payload.getBytes();\n        if (payload.isConsumable()) {\n            InputStream in = null;\n            try {\n                in = payload.toInputStream();\n\n                if (!hasContentType(header)) {   // If there is a content type set, then the application using JJWT is expected\n                    //                          to convert the byte payload themselves based on this content type\n                    //                          https://www.rfc-editor.org/rfc/rfc7515.html#section-4.1.10 :\n                    //\n                    //                          \"This parameter is ignored by JWS implementations; any processing of this\n                    //                          parameter is performed by the JWS application.\"","sourceCodeStart":571,"sourceCodeEnd":607,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java#L571-L607","documentation":"To mitigate decompression DoS (zip-bomb) attacks, JJWT blocks payload decompression for unverified tokens — unprotected JWTs (alg=none) or unencoded JWSs (b64=false) relying on a SigningKeyResolver — unless you explicitly opt in with JwtParserBuilder.unsecuredDecompression(). Hitting this means the token has a zip header but was not integrity-verified by a key-verified path.","triggerScenarios":"Parsing a compressed JWT with alg=none, or an unencoded (b64:false) compressed JWS parsed with a SigningKeyResolver, without calling unsecuredDecompression().","commonSituations":"Accepting unsigned tokens in dev/test environments with compression enabled, legacy unsecured token flows upgraded to newer JJWT versions where the safety gate was added, security-sensitive deployments where the default deny is intentional.","solutions":["Verify the token with a real key (verifyWith/keyLocator) so integrityVerified is true and decompression is allowed.","If unsigned/unencoded compressed tokens are truly required, call .unsecuredDecompression() on the JwtParserBuilder after reading its security JavaDoc.","Remove the zip header from token production for unsecured tokens.","If you never expect compression, inspect the token producer adding a zip header and disable it there."],"exampleFix":"// before\nJwts.parser().build().parse(unsecuredCompressedJwt);\n// after\nJwts.parser().unsecuredDecompression().build().parse(unsecuredCompressedJwt);","handlingStrategy":"try-catch","validationCode":"Map<String,Object> h = getUntrustedHeader(token);\nif (\"none\".equals(h.get(\"alg\")) && h.containsKey(\"zip\") && !unsecuredDecompressionEnabled) {\n    throw new IllegalArgumentException(\"compressed unsecured token rejected\");\n}","typeGuard":null,"tryCatchPattern":"try { parser.parse(token); } catch (UnsupportedJwtException e) { if (e.getMessage().contains(\"UNPROTECTED_DECOMPRESSION\") || e.getMessage().contains(\"decompression\")) { /* verify with a key or opt in deliberately */ } }","preventionTips":["Verify tokens with real keys wherever possible; reserve unsecuredDecompression() for legacy cases.","Never accept alg=none tokens in production without explicit policy.","Disable compression on unsigned tokens at the producer.","Keep JJWT updated and review the security notes on the unsecuredDecompression() JavaDoc when opting in."],"tags":["compression","dos","unsecured-jwt","unencoded-jws"],"backgroundTag":"feature-not-enabled","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"}