spring-projects/spring-security · error · IllegalArgumentException

Failed to decode SAMLResponse

Error message

Failed to decode SAMLResponse

What it means

Saml2Utils' internal decoding pipeline validates that the decoded bytes look like an acceptable SAMLResponse before producing it. checkAcceptable throws this IllegalArgumentException when the decoded payload fails the acceptability checks (e.g. doesn't start with expected XML prefix / fails size or content validation), guarding against malformed or malicious input.

Source

Thrown at saml2/saml2-service-provider/src/main/java/org/springframework/security/saml2/provider/service/metadata/Saml2Utils.java:189

					}
				}

				// in cases of an incomplete final chunk, ensure the unused bits are zero
				switch (goodChars % 4) {
					case 0:
						return true;
					case 2:
						return (lastGoodCharVal & 0b1111) == 0;
					case 3:
						return (lastGoodCharVal & 0b11) == 0;
					default:
						return false;
				}
			}

			void checkAcceptable(String ins) {
				if (!isAcceptable(ins)) {
					throw new IllegalArgumentException("Failed to decode SAMLResponse");
				}
			}

		}

	}

	static class CappedOutputStream extends OutputStream {

		private static final long MAX_SIZE = 1024 * 1024;

		private final OutputStream delegate;

		private int size;

		CappedOutputStream(OutputStream delegate) {
			this.delegate = delegate;
		}

View on GitHub (pinned to 96852e8860)

Solutions

  1. Confirm the SAMLResponse POST parameter is exactly once base64-decoded into well-formed XML starting with the expected XML declaration/saml prefix
  2. Log and inspect the decoded bytes to see what content actually arrived
  3. Check the IdP is configured to use the HTTP-POST binding for responses
  4. Inspect proxies/load balancers for body truncation or re-encoding
  5. If the payload is legitimate and still rejected, compare against the library's isAcceptable constraints (prefix/size) and file an issue

Example fix

// before: blindly decoding
String xml = Saml2Utils.samlDecode(encodedResponse);
// after: pre-validate the parameter
if (encodedResponse == null || encodedResponse.isBlank()) {
    throw new Saml2Exception("Missing SAMLResponse parameter");
}
String xml = Saml2Utils.samlDecode(encodedResponse);
Defensive patterns

Strategy: validation

Validate before calling

boolean looksLikeSamlResponse(String b64) {
    if (b64 == null || b64.isBlank()) return false;
    try {
        String xml = new String(Base64.getMimeDecoder().decode(b64), StandardCharsets.UTF_8);
        return xml.contains("<saml2p:Response") || xml.contains("<samlp:Response");
    } catch (IllegalArgumentException ex) { return false; }
}

Try / catch

try {
    byte[] decoded = Saml2Utils.samlDecode(param);
} catch (IllegalArgumentException | Saml2Exception ex) {
    auditLog.malformedSamlResponse(request.getRemoteAddr());
    throw new Saml2Exception("Malformed SAMLResponse from IdP", ex);
}

Prevention

When it happens

Trigger: Calling the Saml2Utils decode/samlDecode pipeline with a base64 payload whose decoded content is empty, truncated, or does not match the expected SAML XML structure, causing the internal IllegalArgumentException.

Common situations: IdP posts a non-XML or garbage SAMLResponse; double- or missing-base64-encoding of the parameter; truncated POST body due to proxy limits; an attacker or misconfigured IdP sending crafted payloads; tests pasting wrong sample payloads.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/d4bdd97ebf011fd6. Report an issue: GitHub.