{"record":{"id":"66a77533c3eeecf8","repo":"spring-projects/spring-security","slug":"failed-to-decode-samlresponse-66a775","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/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/authentication/logout/Saml2Utils.java#L171-L207","documentation":"Logout-package EncodingConfigurer checkAcceptable validates that the Base64-decoded SAML logout message contains acceptable characters before parsing, as a hardening measure against decoder-confusion attacks. If isAcceptable(ins) fails it throws IllegalArgumentException \"Failed to decode SAMLResponse\".","triggerScenarios":"During logout message decoding, checkAcceptable(ins) is invoked and the decoded string contains disallowed characters — invalid XML content after (optionally inflated) decoding.","commonSituations":"Malformed or tampered SAMLRequest/SAMLResponse/SAMLLogout parameters; incorrect Base64/URL decoding producing garbage; deliberate attack payloads probing the decoder.","solutions":["Ensure parameters are decoded exactly once with the correct Base64 decoder and UTF-8 string conversion","Verify no intermediary (proxy, gateway) is corrupting query parameters","Reject the request — this validation intentionally blocks non-XML input"],"exampleFix":"// before\n String xml = new String(bytes, StandardCharsets.US_ASCII); // drops multibyte chars\n// after\n String xml = new String(bytes, StandardCharsets.UTF_8);","handlingStrategy":"validation","validationCode":"String xml = new String(inflated, StandardCharsets.UTF_8);\nif (!xml.trim().startsWith(\"<\")) {\n    throw new IllegalArgumentException(\"not XML: reject logout message\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    // logout message decoding path\n} catch (IllegalArgumentException e) {\n    // message contains unacceptable characters: reject request\n}","preventionTips":["Single, correct Base64 + UTF-8 decoding of SLO parameters","Check proxies/gateways aren't corrupting parameters","Treat validation failures as untrusted input"],"tags":["saml2","logout","base64","validation"],"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"}