spring-projects/spring-security · error · Saml2Exception

Saml2Exception wrapping MarshallingException while re-marsha

Error message

Saml2Exception wrapping MarshallingException while re-marshalling response after decryption

What it means

After decryption replaces EncryptedAssertions with plain Assertions, the template re-marshals the Response DOM so that decrypted ID attributes are re-established at the DOM level. A MarshallingException during this re-marshall is wrapped in a Saml2Exception.

Source

Thrown at saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/metadata/OpenSaml5Template.java:532

					}
					count++;
				}
				catch (DecryptionException ex) {
					throw new Saml2Exception(ex);
				}
			}

			response.getAssertions().addAll(decrypteds);

			// Re-marshall the response so that any ID attributes within the decrypted
			// Assertions
			// will have their ID-ness re-established at the DOM level.
			if (!decrypteds.isEmpty()) {
				try {
					XMLObjectSupport.marshall(response);
				}
				catch (final MarshallingException ex) {
					throw new Saml2Exception(ex);
				}
			}
		}

		private void decryptAssertion(Assertion assertion) {
			for (AttributeStatement statement : assertion.getAttributeStatements()) {
				decryptAttributes(statement);
			}
			decryptSubject(assertion.getSubject());
			if (assertion.getConditions() != null) {
				for (Condition c : assertion.getConditions().getConditions()) {
					if (!(c instanceof DelegationRestrictionType delegation)) {
						continue;
					}
					for (Delegate d : delegation.getDelegates()) {
						if (d.getEncryptedID() != null) {
							try {
								NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());

View on GitHub (pinned to 96852e8860)

Solutions

  1. Inspect the wrapped MarshallingException for the specific XML element causing the failure and validate the IDP's response against the SAML schema.
  2. Avoid mutating the Response XMLObject between parsing and decrypt(); re-parse the raw XML before decrypting.
  3. Ensure the Response was parsed by OpenSAML's ParserPool so its DOM state is consistent for re-marshalling.
  4. Upgrade spring-security-saml2-service-provider / OpenSAML to a version where the marshalling bug (if any) is fixed.

Example fix

// before
Response response = customParse(rawXml);
template.decrypt(response);
// after
Response response = (Response) XMLObjectProviderRegistrySupport.getParserPool()
    .parse(new ByteArrayInputStream(rawXml)).getXMLObject();
template.decrypt(response);
Defensive patterns

Strategy: try-catch

Try / catch

try {
    template.decrypt(response);
} catch (Saml2Exception ex) {
    if (ex.getCause() instanceof MarshallingException) {
        logger.error("Post-decryption re-marshall failed; check IDP XML for schema violations", ex);
    }
}

Prevention

When it happens

Trigger: Calling decrypt(response) when at least one assertion was decrypted and XMLObjectSupport.marshall(response) fails due to malformed/duplicate XML attributes, null required elements, or an inconsistent object/DOM state after decryption.

Common situations: IDP-issued XML that violates SAML schema (duplicate IDs); prior manual mutation of the Response XMLObject; OpenSAML version behavior change in marshalling; very large messages hitting DOM configuration limits.

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/04642de7dd580700. Report an issue: GitHub.