A retrospective on the protocol nobody can replace

Security firm Trail of Bits published a historical analysis of SAML this week, and the title is not subtle: they call it a fractal of bad design, straightforward on the surface but built on what they describe as a foundation of sand, bone dust, and ash. The post is part of their series of historical security analyses, and it is worth reading even if you never touch a SAML assertion, because it doubles as a lesson in how protocols ossify.

The short version of their argument: SAML is not broken because of one bug. It is broken because the substrate it chose in 2002 forces every implementation to solve problems that better-designed successors simply do not have.

XML is the load-bearing mistake

The core complaint is the foundation layer. SAML signs and carries assertions written in XML, and XML brings its entire parser bug taxonomy with it: XXE injection, billion-laughs expansion, and the canonicalization problems that follow. Trail of Bits points out that a SAML library has to handle all of those bug classes before it can even start doing actual SAML work. Complexity is generally at odds with security, and SAML carries a lot of it for features most deployments never use.

That last part is the sharpest point in the post. The authors note that the overwhelming majority of modern implementations use a very similar data shape and a small subset of the specification. All the un-simplifiable complexity buys almost nothing in practice. The spec froze in place, the industry grew up around it, and nobody can change it now.

Canonicalization and the signature problem

The technical mechanism behind most real SAML attacks is canonicalization. For an XML signature to verify, the service provider and the identity provider must agree on a byte-for-byte canonical form of the document. If the two sides’ parsers disagree about how to canonicalize the same XML, the bytes do not line up, the signatures do not match, and authentication fails. Attackers exploit exactly that gap: parser differentials and round-trip bugs are what most modern SAML attacks use, according to the post.

Enveloped signatures make it worse, because the signature lives inside the payload it is signing. The authors put it bluntly: if you are inserting the signature into the data you are signing, you are going to have a bad time. And most fielded implementations do not even implement this themselves. They wrap libxmlsec, a C codebase the post describes as gnarly and largely unread. Your SSO trust boundary, in many stacks, rests on a library almost nobody has audited line by line.

Born before TLS won

The historical argument explains why the design looks this way. SAML came out of early 2000s academia and federation projects, with Yale’s CAS system in 2002 and Internet2’s Shibboleth identity provider in 2003, at a time when HTTP plus TLS was not yet the backbone of web communication. The protocol was designed for a world where you could not assume the identity provider and the service provider could talk to each other directly. The post argues it never reconciled with the modern landscape: HTTP bindings exist in the spec, but they are not required, so the protocol still has to carry all authentication state inside the signed response payload.

That single design decision creates most of the attack surface. If the response message has to be self-contained and tamper-proof across mutually distrusting parsers, you need canonicalization, you need signatures embedded in the document, and you inherit every failure mode listed above.

OIDC as the exit ramp

The contrast with OpenID Connect is structural, not cosmetic. OIDC assumes a connected topology: in the authorization code flow, the provider and the relying party communicate directly, so the tokens do not have to carry every claim inline through a hostile parser. That removes the exact surface SAML’s design forces into its assertions.

The most practical part of the post is the migration suggestion. The authors argue that OIDC’s implicit flow with form post response mode provides the same ingredients SAML deployments rely on, and call it one of the cleaner migration paths available in the industry. Their advice for organizations is to hold the line on OIDC when vendors push back, citing Tailscale as proof that a company can insist on it and survive. Procurement leverage is the actual tool here: suppliers who refuse real SSO integration tend to have competitors who do not.

What this means in practice

Realistically, SAML is not going away. Enterprise SSO contracts, legacy identity providers, and a hundred product integrations keep it alive, and most SAML deployments work fine day to day. The value of a post like this is not panic, it is prioritization. If you are building a new SSO integration, choose OIDC first and treat SAML as the compatibility mode you support because a customer demands it. If you maintain SAML code, the audit surface to care about is canonicalization and parser behavior, not the protocol tables in the spec.

My take: this is the kind of post that ages well. The specific bugs change, the pattern does not. Protocols that force signed, parser-sensitive payloads across trust boundaries keep producing CVEs, and every generation rediscovers it. OIDC has its own share of implementation footguns, but moving the negotiation off the wire and onto a direct channel is the right direction, and it is nice to see a security firm say the quiet part plainly: some protocols are not worth patching, they are worth leaving.

Leave a Reply

Your email address will not be published. Required fields are marked *