A SAML response can contain a cryptographically valid XML Signature while the application consumes an assertion the signature never protected. This is the practical danger behind signature wrapping. The parser verifies one element, another element carries the attacker's identity, and both paths look reasonable to developers reading only the happy case.
The failure pattern
An XML Signature contains a Reference that identifies the data covered by the digest. Validation succeeds only when the referenced bytes, canonicalization and digest calculation all agree. Wrapping attacks exploit a mismatch between that verified reference and the element the application later trusts.
Duplicate assertions, copied identifiers or a signature placed beside rather than over the assertion can create the gap. A common mistake is to search the document for the first assertion and validate the first signature independently. The application then reads a second assertion whose identifier appears inside the signed material but whose content is not covered by the selected signature.
Make the trust decision explicit
Validate the signature, then return the exact signed assertion object to the authorization code. Do not re-query the XML tree for an assertion by identifier. Reject multiple top-level assertions unless the profile explicitly permits them, reject duplicate identifiers, and reject signatures that cover an object other than the assertion being consumed.
Check the signed subject, audience and recipient against the local service provider. Confirm that any InResponseTo value matches an outstanding authentication request when the profile uses one. Apply time conditions after signature verification and use parser settings that disable external entities and unrelated network resolution.
Canonicalization needs the same discipline. A verifier that normalizes one subtree while the application reads another can reintroduce the mismatch. Keep signature verification inside a reviewed library, pass the verified node forward, and avoid custom XML string manipulation around identifiers.
Test the negative tree
Build negative tests with two assertions sharing an identifier, a valid signature over a benign assertion followed by a privileged assertion, a modified Audience value and an assertion moved outside its signed response. Each test should fail before user lookup or session creation.
Log the reference URI, the identifier of the assertion selected for authorization and the signature result. Do not log complete assertions because they can contain personal data and bearer attributes.
The check is simple to state: the assertion that creates the session must be the assertion the signature proves. Any application path that loses that relationship should be treated as an authentication boundary failure.