{"record":{"id":"1e1a62f10a5720d5","repo":"spring-projects/spring-security","slug":"unable-to-inflate-string-1e1a62","errorCode":null,"errorMessage":"Unable to inflate string","messagePattern":"Unable to inflate string","errorType":"exception","errorClass":"Saml2Exception","httpStatus":null,"severity":"error","filePath":"saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/logout/Saml2Utils.java","lineNumber":74,"sourceCode":"\t\t\tdeflater.write(s.getBytes(StandardCharsets.UTF_8));\n\t\t\tdeflater.finish();\n\t\t\treturn b.toByteArray();\n\t\t}\n\t\tcatch (IOException ex) {\n\t\t\tthrow new Saml2Exception(\"Unable to deflate string\", ex);\n\t\t}\n\t}\n\n\tstatic String samlInflate(byte[] b) {\n\t\ttry {\n\t\t\tByteArrayOutputStream out = new ByteArrayOutputStream();\n\t\t\tInflaterOutputStream iout = new InflaterOutputStream(new CappedOutputStream(out), new Inflater(true));\n\t\t\tiout.write(b);\n\t\t\tiout.finish();\n\t\t\treturn new String(out.toByteArray(), StandardCharsets.UTF_8);\n\t\t}\n\t\tcatch (IOException ex) {\n\t\t\tthrow new Saml2Exception(\"Unable to inflate string\", ex);\n\t\t}\n\t}\n\n\tstatic EncodingConfigurer withDecoded(String decoded) {\n\t\treturn new EncodingConfigurer(decoded);\n\t}\n\n\tstatic DecodingConfigurer withEncoded(String encoded) {\n\t\treturn new DecodingConfigurer(encoded);\n\t}\n\n\tstatic final class EncodingConfigurer {\n\n\t\tprivate final String decoded;\n\n\t\tprivate boolean deflate;\n\n\t\tprivate EncodingConfigurer(String decoded) {","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/authentication/logout/Saml2Utils.java#L56-L92","documentation":"Logout-package Saml2Utils.samlInflate decompresses a DEFLATE-encoded SAML logout message from HTTP-Redirect binding. Saml2Exception \"Unable to inflate string\" is thrown when decompression fails: input is not raw-DEFLATE, is corrupt/truncated, or exceeds the CappedOutputStream limit.","triggerScenarios":"logout Saml2Utils.samlInflate(byte[] b) writes to InflaterOutputStream over CappedOutputStream; corrupt/non-raw-deflate bytes or oversized payload trigger IOException and the exception.","commonSituations":"Logout request/response parameter corrupted in transit, wrong Base64 decoding before inflation, IdP emitting zlib-wrapped data, or a malicious oversized SLO payload hitting the cap.","solutions":["Verify single, correct Base64 decoding of the SAMLRequest/SAMLResponse/SAMLLogout parameter before inflation","Confirm the IdP compresses with raw DEFLATE per redirect-binding spec","Use HTTP-POST binding for large logout messages that hit the size cap","Log the wrapped cause to distinguish corruption from decompression-bomb attempts"],"exampleFix":"// before\n byte[] raw = Base64.getDecoder().decode(Base64.getDecoder().decode(param)); // double decode\n// after\n byte[] raw = Base64.getDecoder().decode(param);","handlingStrategy":"try-catch","validationCode":"byte[] raw;\ntry { raw = Base64.getDecoder().decode(b64Param); }\ncatch (IllegalArgumentException e) { return null; }\nif (raw.length > MAX_EXPECTED_COMPRESSED) return null;","typeGuard":null,"tryCatchPattern":"try {\n    String xml = Saml2Utils.samlInflate(raw);\n} catch (Saml2Exception e) {\n    // corrupt logout message or size cap exceeded; reject and log\n}","preventionTips":["Decode SAML logout parameters exactly once","Confirm IdP raw-DEFLATE compression","Reject oversized payloads as potential bombs","Fall back to POST binding for large SLO messages"],"tags":["saml2","logout","inflate","compression"],"backgroundTag":"compression-failed","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}