In this article
October 1, 2026
October 1, 2026

Trail of Bits is right about SAML. You still have to support it.

SAML's security record is as bad as Trail of Bits says. Here's why B2B SaaS teams still have to support it, and how to keep the XML out of their own code.

Explore with AI
Open in ChatGPT
Open in Claude
Open in Perplexity

On September 21, Trail of Bits published SAML: A fractal of bad design. It argues that SAML "is being crushed under the weight of its own complexity" and should be deprecated in favor of OpenID Connect. Its advice for service providers is short: support OIDC and abandon SAML. The post reached the front page of Hacker News, where the thread became a long argument between people who build SAML integrations and people who buy them.

We agree with most of the diagnosis. We disagree with the prescription, at least for anyone selling software to enterprises. This post covers both.

Where Trail of Bits is right

The core of the critique is XML signatures. Before an identity provider (IdP) can sign an assertion, or a service provider (SP) can verify it, both sides have to canonicalize the XML: reduce it to one exact byte representation. If two parsers disagree about what the document says, the signature checks out over one version while the application reads another. SAML also places its signature inside the element being signed, which makes that byte-for-byte agreement harder to get right.

Diagram of one SAML response read by two parsers. The signature verifier reads the signed assertion for alice and reports the signature as valid. The application logic reads an attacker-inserted assertion for admin and creates an admin session.
Same bytes, two readings. Most modern SAML bypasses come from two parsers disagreeing about one document. The signature is valid, just over a different assertion than the one the application uses.

This isn't a theory. The Trail of Bits timeline runs from signature-wrapping papers in 2005 to GitHub Security Lab's parser differential bypass in ruby-saml and PortSwigger's The Fragile Lock in 2025. We covered the next wave in SAML's rough quarter in April: five critical vulnerabilities in four months, across Citrix, Authentik, OneUptime and others.

The kitchen-sink point holds too. Real deployments use a small subset of the spec, but parsers still have to deal with everything the spec allows. That's why the post repeats Thomas Ptacek's advice to reject any message that doesn't look like what Okta, OneLogin, Google or Shibboleth actually generate.

None of this is news to us. Our developer's guide to SAML already says it plainly: if you can avoid SAML and choose OIDC, do.

September made the case again

Two disclosures from this month show that the attack surface goes beyond the signature.

On September 9, Drupal published 11 advisories for its SAML SSO Service Provider module in one day. They cover improper access control, certificate validation, replay protection, open redirects and server-side request forgery. All are fixed in version 3.2.0. On September 20, CVE-2026-82842 was disclosed in a WordPress SAML plugin. The plugin ignored the site's configured rule for linking an SSO identity to an account and always matched on login name. Anyone who could get the IdP to assert a chosen login name could sign in as any account, including an administrator.

Neither of these is a canonicalization bug. They live in the code around the assertion: admin configuration, account linking, redirects. That matters for what comes next.

Diagram of four layers in a service provider's SSO code, each with a recent example. Admin configuration: Drupal SA-CONTRIB-2026-141, improper access control. Account linking: WordPress CVE-2026-82842, matched on login name. Claim validation: Drupal SA-CONTRIB-2026-150, insufficient replay protection. Token verification, highlighted as the only layer a protocol switch replaces: ruby-saml and The Fragile Lock for SAML in 2025, and Microsoft Titan accepting an unsigned JWT for OIDC in 2026.
Switching protocols replaces one layer. The other three stay in your code whether the customer's IdP speaks SAML or OIDC.

Where "just support OIDC" breaks down

For identity providers, the deprecation plan Trail of Bits describes is reasonable. Stop onboarding new SAML customers, offer equivalent OIDC configurations and set a sunset date. For SaaS vendors, four things get in the way.

Your customer picks the protocol, not you

The Trail of Bits post quotes Ptacek saying Fly.io and Tailscale have "held the line" on OIDC only. That works if you have leverage. A seed-stage company working on its first six-figure contract usually doesn't. If the customer's IdP is an AD FS deployment that only its IT team knows how to configure, or the customer belongs to a SAML federation like InCommon, the security review will ask for SAML, and declining means losing the deal. We wrote about why that installed base lasts in why a two-decade-old protocol still dominates identity federation. One HN commenter summed up the vendor side: it's "an addressable market versus development cost question."

The same thread also had a hopeful data point. One vendor reported that "most people asking for SAML can actually do OIDC and are happy to do so." So offer OIDC first and ask. Just don't make it the only option.

Some SAML arguments are weaker than they sound

SAML's defenders on HN raised two points that deserve a closer look.

First, IdP-initiated sign-in. OIDC isn't missing this. OIDC Core defines third-party initiated login through an initiate_login_uri, so a user can click a tile in an IdP dashboard and land in your app. Whether a given customer's IdP and admin have set it up is a per-customer question, but the protocol supports it.

Second, IdPs on private networks. Trail of Bits answers this one: OIDC with the form post response mode sends the response through the browser, the same way SAML does.

These are good reasons to push customers toward OIDC. They don't make SAML optional.

OIDC is a standard, but identity providers aren't

OIDC is easier to implement, but providers don't all read the spec the same way. Last month we described the per-connection compatibility settings we added for generic OIDC: client authentication method, ID token signing algorithm, and whether to fetch claims from the UserInfo endpoint. Each one exists because a real provider behaved differently from the others.

Sometimes OIDC is clearly the better tool for a specific hop. Mike Crowley's write-up on federating Okta and Entra ID shows that Okta can learn Entra completed MFA from the amr claim in an OIDC ID token, but can't read the same fact from Entra's SAML response. That's an argument for knowing both protocols well, not for dropping one.

JSON doesn't validate itself

Switching to OIDC changes how you fail, not whether you can. In a write-up published September 25, a researcher showed how Titan, an internal Microsoft analytics service, checked tenant, audience, application ID and user claims on incoming JWTs but never verified the signature. An unsigned token with "alg": "none" and a username of admin got query access to roughly 17 trillion rows. The fix was the same one that keeps coming up for SAML: verify the signature first, with a pinned algorithm, before trusting any claim. Our JWT best practices covers what that looks like in code.

The real decision is who runs the parser

When an enterprise customer asks for SSO, a SaaS team has three realistic options.

Option What you maintain Deals you can close When it fits
Build SAML and OIDC yourself An XML signature stack and a JOSE stack, plus account linking, certificate rotation and IdP quirks for each All of them Federation is your product, or you have a dedicated identity team
Support only OIDC One smaller, safer stack Customers whose IdP and IT team can do OIDC Cloud-native customers on Okta, Entra ID or Google Workspace, and a sales team that has agreed to the tradeoff
Delegate both protocols One OAuth 2.0 style flow and a normalized profile All of them SSO is a requirement for selling, not the product you sell

‍

Whichever you choose, SSO is only half of what the customer asked for. As one commenter put it, both protocols "will pale compared to the amount of time you spend dealing with SCIM inconsistencies between IdPs anyway." Users who leave the company still need to lose access.

If SAML stays in your own code

If you keep your own SAML implementation, the September disclosures add two items to the usual checklist:

  • Link identities on a stable, configured attribute and enforce it. Never fall back to a username or email the IdP can assert freely. The WordPress bug was exactly this fallback.
  • Treat SSO configuration as privileged. Metadata, certificates and redirect targets are admin surfaces. The Drupal advisories started with improper access control on configuration.

The rest of the list hasn't changed. Use a maintained library with one parser instance for the whole response. Reject messages that don't match the shape your known IdPs produce. Validate issuer, audience, recipient, destination, timestamps and InResponseTo. Keep a replay cache of assertion IDs. Our SAML security best practices guide goes through each one.

How WorkOS handles it

WorkOS SSO puts SAML and OIDC behind one OAuth 2.0 style integration, so your application never parses an assertion. WorkOS validates signatures, audience restrictions, timestamps and assertion IDs on every SAML response before your app sees a profile. OIDC connections get the per-connection compatibility settings described above. Your customers' IT admins set up their own connections in the Admin Portal and choose OIDC when their IdP supports it, so you don't have to pick for them. When they also need provisioning, Directory Sync handles SCIM on the same platform.

SAML had a good run

Trail of Bits ends by thanking SAML for a 25-year run, and that's fair. The protocol created the SSO industry, and its security problems are structural, not bad luck. But retiring a protocol is the identity providers' job. For the people building SaaS products, the job for now is narrower: offer OIDC first, support SAML for the customers who need it, and make sure the XML parsing that's left happens somewhere it's maintained full-time.