{"record":{"id":"eedbe1b72413102e","repo":"spring-projects/spring-security","slug":"saml2exception-wrapping-marshallingexception-while-eedbe1","errorCode":null,"errorMessage":"Saml2Exception wrapping MarshallingException while re-marshalling response after decryption","messagePattern":"Saml2Exception wrapping MarshallingException while re-marshalling response after decryption","errorType":"exception","errorClass":"Saml2Exception","httpStatus":null,"severity":"error","filePath":"saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/registration/OpenSaml5Template.java","lineNumber":532,"sourceCode":"\t\t\t\t\t}\n\t\t\t\t\tcount++;\n\t\t\t\t}\n\t\t\t\tcatch (DecryptionException ex) {\n\t\t\t\t\tthrow new Saml2Exception(ex);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tresponse.getAssertions().addAll(decrypteds);\n\n\t\t\t// Re-marshall the response so that any ID attributes within the decrypted\n\t\t\t// Assertions\n\t\t\t// will have their ID-ness re-established at the DOM level.\n\t\t\tif (!decrypteds.isEmpty()) {\n\t\t\t\ttry {\n\t\t\t\t\tXMLObjectSupport.marshall(response);\n\t\t\t\t}\n\t\t\t\tcatch (final MarshallingException ex) {\n\t\t\t\t\tthrow new Saml2Exception(ex);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tprivate void decryptAssertion(Assertion assertion) {\n\t\t\tfor (AttributeStatement statement : assertion.getAttributeStatements()) {\n\t\t\t\tdecryptAttributes(statement);\n\t\t\t}\n\t\t\tdecryptSubject(assertion.getSubject());\n\t\t\tif (assertion.getConditions() != null) {\n\t\t\t\tfor (Condition c : assertion.getConditions().getConditions()) {\n\t\t\t\t\tif (!(c instanceof DelegationRestrictionType delegation)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tfor (Delegate d : delegation.getDelegates()) {\n\t\t\t\t\t\tif (d.getEncryptedID() != null) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tNameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/registration/OpenSaml5Template.java#L514-L550","documentation":"After decrypting embedded assertions, decryptResponse() re-marshals the Response via XMLObjectSupport.marshall so decrypted assertions' ID attributes are re-established at the DOM level; a MarshallingException there is wrapped in this Saml2Exception. The decryption itself succeeded but the resulting Response could not be converted back to DOM.","triggerScenarios":"Any successful decryption of at least one encrypted assertion followed by a marshalling failure — typically due to an inconsistent DOM state after decryption, namespace issues, or OpenSAML registry/marshaller problems for the decrypted content.","commonSituations":"Corrupted or nonstandard IdP response whose decrypted subtree cannot be re-marshalled; OpenSAML version conflicts altering marshaller behavior; custom unmarshallers producing XMLObjects that don't round-trip through marshall().","solutions":["Inspect ex.getCause()/stack trace for why XMLObjectSupport.marshall failed and compare the raw (encrypted) response","Upgrade/align OpenSAML 5 jars so unmarshaller/marshaller registries are consistent","Work around by re-building the XMLObject tree from the decrypted data instead of relying on re-marshall, or log the raw response and report to the IdP if it emits nonstandard encrypted elements","Check for custom unmarshallers or extensions that produce XMLObjects with invalid namespace declarations"],"exampleFix":"// before\n// assuming any response can be re-marshalled silently\n// after\ntry {\n    template.deserialize(rawResponseString);\n} catch (Saml2Exception ex) {\n    logger.warn(\"Persist raw response for diagnosis before decryption\", ex);\n    throw ex;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    Response decrypted = template.decrypt(response);\n} catch (Saml2Exception ex) {\n    logger.warn(\"Re-marshall after decryption failed; raw response preserved for diagnosis\", ex);\n    throw ex;\n}","preventionTips":["Persist the raw response (securely) before decrypting so failures are diagnosable","Keep OpenSAML dependencies aligned to a single version","Report IdPs that emit nonstandard encrypted assertion structures"],"tags":["saml2","opensaml","decryption","marshalling"],"backgroundTag":"internal-invariant-violation","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"}