# SAML assertion identity and audience not bound

SAML SP/IdP skipping or loosely comparing Audience, Destination/Recipient, ACS URL or issuer before minting a session

_Area: Web authentication and account takeover. Seen in 3 disclosed reports; 2 confirmed bounties: $3,000 and $10,500; latest 2026-04-29. Updated 2026-11-02._

## How it works
A SAML assertion is a signed statement, but the signature only proves the IdP said it. The SP must still bind the statement to *itself* and to the *right identity*: the Audience must name this SP, the Destination/Recipient must be a registered ACS URL, and the issuer/entityId used to authenticate must be the same key used to provision or look up the account. When any comparison is skipped, done on a normalized value in one place and a raw value in another, or taken from the request instead of stored config, the assertion is accepted for a context it was never minted for. The broken assumption: "a valid signature means this assertion is for us and about this user."

## Where it shows up
- Issuer/entityId trimmed or lowercased for signature check but used untrimmed as a DB lookup key [E1](https://bugbountylibrary.com/r/h1%3A976603.md)
- No AudienceRestriction/Audience check before session mint [E3](https://bugbountylibrary.com/r/blog%3Ablog-intothesymmetry-com-2017-10-slack-saml-authentication-bypass-html.md)
- `AssertionConsumerServiceURL` read from the AuthnRequest and used as Destination/Recipient without comparing to the stored per-client ACS [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-p9w9-87c8-m235.md)
- The same unchecked ACS path repeated in error/logout responses [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-p9w9-87c8-m235.md)

## How to review
Trace one assertion end to end and confirm a single canonical value is used everywhere:
- The issuer/entityId that authenticates must be byte-identical to the key that provisions/looks up the org; no trim/case/unicode divergence between the two call sites [E1](https://bugbountylibrary.com/r/h1%3A976603.md).
- Audience must be checked against this SP's own entity id [E3](https://bugbountylibrary.com/r/blog%3Ablog-intothesymmetry-com-2017-10-slack-saml-authentication-bypass-html.md).
- Destination and SubjectConfirmationData Recipient must equal the client's *stored* ACS URL, never a request-supplied one, on success and error paths alike [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-p9w9-87c8-m235.md).
The invariant: every field that selects *who* and *where* is compared to trusted stored config, not to attacker-influenced input, and the same normalized form is used at every comparison.

## How finders spotted it
- Days probing SSO org-assignment, noticing auth and provisioning resolved to different orgs, then testing a trailing-space entityId to confirm trim-vs-untrimmed divergence [E1](https://bugbountylibrary.com/r/h1%3A976603.md)
- Code review of `handleSSORequest`: `$clientACS` taken from the request and used as Destination/Recipient with no comparison to `smc_acs_url`; noted signature validation is conditional and default-off [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-p9w9-87c8-m235.md)
- Learning SAML from the spec, then presenting an assertion meant for SP B to SP A to test cross-SP reuse [E3](https://bugbountylibrary.com/r/blog%3Ablog-intothesymmetry-com-2017-10-slack-saml-authentication-bypass-html.md)

## Variants seen
- Normalization mismatch: trimmed vs untrimmed entityId splits auth from provisioning [E1](https://bugbountylibrary.com/r/h1%3A976603.md)
- Request-supplied ACS URL: IdP sends signed assertion to an attacker-chosen URL for replay [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-p9w9-87c8-m235.md)
- Missing Audience check: assertion for another SP accepted [E3](https://bugbountylibrary.com/r/blog%3Ablog-intothesymmetry-com-2017-10-slack-saml-authentication-bypass-html.md)

## Impact and severity
Ranged from SSO DoS to cross-org provisioning and full account takeover, including access to personal documents [E1](https://bugbountylibrary.com/r/h1%3A976603.md); impersonation on separate SP applications via assertion replay [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-p9w9-87c8-m235.md); and login as an arbitrary subject on the target SP [E3](https://bugbountylibrary.com/r/blog%3Ablog-intothesymmetry-com-2017-10-slack-saml-authentication-bypass-html.md). Impact rose when the flaw crossed org or SP boundaries [E1](https://bugbountylibrary.com/r/h1%3A976603.md)[E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-p9w9-87c8-m235.md).

## Evidence
- E1: https://bugbountylibrary.com/r/h1%3A976603.md
- E2: https://bugbountylibrary.com/r/ghsa%3AGHSA-p9w9-87c8-m235.md
- E3: https://bugbountylibrary.com/r/blog%3Ablog-intothesymmetry-com-2017-10-slack-saml-authentication-bypass-html.md
