{"record":{"id":"d0782c0511081451","repo":"spring-projects/spring-security","slug":"unable-to-inflate-string-d0782c","errorCode":null,"errorMessage":"Unable to inflate string","messagePattern":"Unable to inflate string","errorType":"exception","errorClass":"Saml2Exception","httpStatus":500,"severity":"error","filePath":"saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/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/web/Saml2Utils.java#L56-L92","documentation":"Saml2Utils.samlInflate decompresses a DEFLATE-compressed (raw, no zlib header) SAML payload, typically the redirect-binding SAMLRequest/SAMLResponse. Any IOException from the InflaterOutputStream — corrupt or truncated compressed bytes — is wrapped in this Saml2Exception.","triggerScenarios":"Calling samlInflate (directly or via Saml2RedirectAuthenticationRequestResolver flows that decode+inflate) with bytes that are not valid raw-DEFLATE data: wrong URL-decoding, double-decoding, decoding base64 that isn't DEFLATE-compressed, or truncated parameters.","commonSituations":"The IdP signs/sends uncompressed SAMLRequest while the SP expects DEFLATE; the b64 value was already decoded once (e.g. by a proxy or prior Base64.decode) and then decoded/inflated again; query-string characters (+, %) mangled by manual URL decoding; relay/SAML parameter truncated by a proxy with a URL length limit.","solutions":["Verify the input is URL-decoded exactly once and then Base64-decoded exactly once before inflation (use Saml2Utils.withDecoded(...).inflate() pipeline rather than manual steps).","Check whether the IdP actually applies DEFLATE compression on redirect bindings; if it does not, skip inflation and parse the decoded XML directly.","Log the byte length and first bytes of the payload; truncated input (payload cut by proxies) must be fixed at the proxy/max-URL-length level.","Catch Saml2Exception around redirect-binding processing and return a 400 with guidance instead of a 500."],"exampleFix":"// before\nbyte[] decoded = Base64.getDecoder().decode(b64);\nString xml = Saml2Utils.samlInflate(decoded); // fails when payload is plain XML\n// after\nString decoded = new String(Base64.getDecoder().decode(b64), StandardCharsets.UTF_8);\nString xml = decoded.contains(\"<saml2p:\") || decoded.contains(\"<samlp:\") ? decoded : Saml2Utils.samlInflate(Base64.getDecoder().decode(b64));","handlingStrategy":"try-catch","validationCode":"String decoded = new String(Base64.getDecoder().decode(b64), StandardCharsets.UTF_8);\nif (decoded.contains(\"<saml\") || decoded.contains(\"<samlp\")) return decoded; // already plain XML","typeGuard":null,"tryCatchPattern":"try {\n    String xml = Saml2Utils.samlInflate(bytes);\n} catch (Saml2Exception ex) {\n    logger.warn(\"Bad SAML redirect payload\", ex);\n    response.sendError(HttpServletResponse.SC_BAD_REQUEST);\n}","preventionTips":["Decode exactly once: URL-decode then base64-decode, never both twice","Confirm the IdP applies DEFLATE compression on redirect bindings before assuming it","Never manually pre-process SAMLRequest/SAMLResponse parameters before handing them to Spring's resolvers"],"tags":["saml2","spring-security","deflate","decoding"],"backgroundTag":"invalid-argument-format","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"}