{"record":{"id":"cad4ab190206cec3","repo":"spring-projects/spring-security","slug":"failed-to-decode-samlresponse-cad4ab","errorCode":null,"errorMessage":"Failed to decode SAMLResponse","messagePattern":"Failed to decode SAMLResponse","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2Utils.java","lineNumber":189,"sourceCode":"\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// in cases of an incomplete final chunk, ensure the unused bits are zero\n\t\t\t\tswitch (goodChars % 4) {\n\t\t\t\t\tcase 0:\n\t\t\t\t\t\treturn true;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\treturn (lastGoodCharVal & 0b1111) == 0;\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\treturn (lastGoodCharVal & 0b11) == 0;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvoid checkAcceptable(String ins) {\n\t\t\t\tif (!isAcceptable(ins)) {\n\t\t\t\t\tthrow new IllegalArgumentException(\"Failed to decode SAMLResponse\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tstatic class CappedOutputStream extends OutputStream {\n\n\t\tprivate static final long MAX_SIZE = 1024 * 1024;\n\n\t\tprivate final OutputStream delegate;\n\n\t\tprivate int size;\n\n\t\tCappedOutputStream(OutputStream delegate) {\n\t\t\tthis.delegate = delegate;\n\t\t}","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/web/authentication/logout/Saml2Utils.java#L171-L207","documentation":"Identical acceptability check to the authentication-side Saml2Utils, but in the logout package: after base64-decoding an incoming SAML logout message, the decoded content must start with '<' and contain only acceptable characters, otherwise IllegalArgumentException('Failed to decode SAMLResponse') is thrown. The message text is legacy even though this path handles logout messages.","triggerScenarios":"A SAMLLogoutRequest/SAMLLogoutResponse/SLO parameter whose base64-decoded bytes do not begin with '<' — double-encoded, deflated-but-not-decoded mismatch, corrupted form field, or wrong parameter posted to the logout endpoint.","commonSituations":"Misconfigured IDP SingleLogout binding (Redirect-style deflated+encoded value sent via POST); corrupted SLO messages through proxies; test tools posting the wrong parameter name.","solutions":["Verify the IDP's SingleLogoutService binding matches the SP's configured binding (POST sends plain base64 XML)","Manually base64-decode the offending parameter and check the leading byte is '<'","Check URL-encoding integrity of the form/query parameter through any proxies","Regenerate IDP metadata so bindings are negotiated correctly"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"byte[] decoded = Base64.getDecoder().decode(sloParam);\nif (decoded.length == 0 || decoded[0] != '<') {\n    throw new IllegalArgumentException(\"SLO message is not base64-encoded XML\");\n}","typeGuard":null,"tryCatchPattern":"try { /* logout processing */ } catch (IllegalArgumentException ex) {\n    log.warn(\"Malformed SAML logout message\", ex);\n    response.sendError(HttpServletResponse.SC_BAD_REQUEST);\n}","preventionTips":["Keep IDP SingleLogoutService binding consistent with SP registration","Re-generate IDP metadata when bindings change","Verify parameter names/encodings in test tooling posting SLO messages"],"tags":["saml2","spring-security","logout","base64","malformed-input"],"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"}