In this article
March 14, 2025
March 14, 2025

SAMLStorm: Critical Authentication Bypass in xml-crypto and Node.js libraries

Any service using xml-crypto or a Node.js SAML implementation using it, should update immediately to the latest version. WorkOS customers are safe and were not impacted.

Any service using xml-crypto or a Node.js SAML implementation using it, should update immediately to the latest version. WorkOS customers are safe and were not impacted.

On Tuesday, March 4, 2025, WorkOS received a critical security report from researcher Alexander Tan (ahacker1) detailing a zero-day vulnerability in the widely used xml-crypto and SAML libraries in the Node.js ecosystem. This flaw allows attackers to forge SAML authentication responses, potentially granting unauthorized access to any user account in affected applications—including admin accounts—without any user interaction. If exploited, this vulnerability could enable full account takeovers across organizations relying on SAML-based single sign-on (SSO).

WorkOS immediately mobilized its security and engineering teams, following an established incident response process to assess the risk and deploy a fix. Within 24 hours, WorkOS had patched the vulnerability for all customers, ensuring no WorkOS-integrated applications remained exposed. A thorough review of system logs confirmed no evidence of past compromise affecting WorkOS customers.

To further protect the broader cloud ecosystem, WorkOS proactively worked with other identity platforms, various startups, and library maintainers, to accelerate remediation efforts across the industry.

The SAMLStorm vulnerability affects the xml-crypto Node.js library (v6.0.0 and earlier, CVE-2025-29775 & CVE-2025-29774), with a fix introduced in v6.0.1 and backported to v3.2.1 and v2.1.6. It also affects Node.js SAML implementations including @node-saml/node-saml, samlify, saml2-js, samlp, saml2-suomifi, and others. Collectively these packages have over 500k weekly downloads.

Full technical details of this exploit, how it works, and remediation steps for non-WorkOS services are covered below.

How this zero-day enables full account takeovers

Before diving into the details of the SAML protocol and how this vulnerability works, it’s important to first outline the potential impact at a high level.

Any company providing SSO services via SAML that uses the xml-crypto library is at risk. In the worst case, an external threat actor could forge arbitrary assertions for a SAML identity provider (IdP), potentially leading to full account takeovers within affected service providers depending on their security measures.

This exploit requires no user interaction, meaning an attacker could gain unauthorized access to the targeted application with escalated privileges.

SAML basics: understanding the attack surface

There are two similar but distinct vulnerabilities in xml-crypto represented by CVE-2025-29775 & CVE-2025-29774, the first which is exploitable via node-saml and the second which is not. For brevity, this post focuses only on the vulnerability and exploitation vector that affect usage of node-saml, and which were initially reported to WorkOS.

To understand this vulnerability, we first need to understand a bit about how SAML works.

Diagram of a normal SAML flow

In a normal SAML flow:

  1. A user attempts to access the service provider.
  2. The service provider creates an XML-based SAML request.
  3. The browser redirects to the IdP with the SAML request.
  4. The IdP processes the SAML request and asks the user to authenticate.
  5. The IdP generates a SAML response with an assertion and returns it to the browser. In SAML, assertions are used to communicate details about an identity.
  6. The browser forwards the SAML response with the assertion back to the service provider. In the exploit, this is the step where the SAML response would be forged.
  7. The service provider validates the SAML response and returns the authentication context to the browser if valid.

Here is what a normal SAML response looks like:

<saml2p:Response Destination="acsurl" ID="id1857861521424404880641928" ...>
    ...
    <saml2:Assertion ID="id1857861521593646366230134" ...>
        <saml2:Issuer>samlissuer</saml2:Issuer>
        <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
            <ds:SignedInfo>
                <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
                <ds:Reference URI="#id1857861521593646366230134">
                    ...
                    <ds:DigestValue>puw8MLNZ67893HzfgbpLjGPfsdSBJueFbcSw2neguIuk=</ds:DigestValue>
                </ds:Reference>
            </ds:SignedInfo>
            <ds:SignatureValue>assertionsignaturevalue</ds:SignatureValue>
            <ds:KeyInfo>
                <ds:X509Data>
                    <ds:X509Certificate>x509certificate</ds:X509Certificate>
                </ds:X509Data>
            </ds:KeyInfo>
        </ds:Signature>
        <saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
            ...
        </saml2:Subject>
        ...
        <saml2:AttributeStatement>
            <saml2:Attribute Name="id">
                <saml2:AttributeValue ...>idp-id</saml2:AttributeValue>
            </saml2:Attribute>
        </saml2:AttributeStatement>
    </saml2:Assertion>
</saml2p:Response>

How an attacker would exploit this vulnerability

There are a few general conditions that must be met to exploit a service provider:

  1. The service provider must be using xml-crypto.
  2. The attacker needs any valid signature and digest pair from an identity provider.
  3. The service provider needs to trust the identity provider’s certificate in its SAML configuration.
  4. The attacker needs access to the ACS URL, SP Entity ID, and IdP Entity ID:
    1. ACS URL – The endpoint where the Identity Provider sends its authentication response.
    2. SP Entity ID – A URI that identifies the audience of the SAML response.
    3. IdP Entity ID – A URI that identifies the issuer of the SAML response.

These conditions lead to the following exploitation scenarios:

Attack path 1: full access without an account

How the attack works for a threat actor without an identity in the identity provider:

Attack path 1: full access without an account
  1. Go to the target app using an email that redirects to an identity provider with publicly signed metadata. Note that this is not a security vulnerability in these identity providers—they simply provide information that an attacker could use to exploit the flaw in xml-crypto.
  2. When attempting to sign in, a SAML request will be issued, from which you can pull the ACS URL and SP Entity ID, which is necessary to craft the SAML response
  3. Pull the certificate and signature info, as well as the IdP Entity ID, from the public metadata
  4. Craft a SAML response with the certificate and signed value from metadata
  5. Modify the SAML assertion
  6. Recalculate the DigestValue and insert it as comment before the existing digest value within the DigestValue node
  7. Send a request with the crafted SAML response to the ACS URL
  8. The service provider validates the response, and you’ve authenticated

Note this exploitation scenario partially relies on the SP-initiated flow to get the ACS URL and SP Entity ID, but sometimes ACS URLs and SP Entity IDs are predictable and documented.Here is what a tampered SAML response might look like:

<saml2p:Response Destination="acsurl" ID="id1857861521424404880641928" ...>
    ...
    <saml2:Assertion ID="id1857861521593646366230134" ...>
        <saml2:Issuer>samlissuer</saml2:Issuer>
        <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
            <ds:SignedInfo>
                <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
                <ds:Reference URI="#id1857861521593646366230134">
                    ...
                    <ds:DigestValue><!--3YjA3OTNjZWQ1GI5YjljNjgzOWZiZWI5OWY1ZTk1ZDk=-->puw8MLNZ67893HzfgbpLjGPfsdSBJueFbcSw2neguIuk=</ds:DigestValue>
                </ds:Reference>
            </ds:SignedInfo>
            <ds:SignatureValue>assertionsignaturevalue</ds:SignatureValue>
            <ds:KeyInfo>
                <ds:X509Data>
                    <ds:X509Certificate>x509certificate</ds:X509Certificate>
                </ds:X509Data>
            </ds:KeyInfo>
        </ds:Signature>
        <saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
            ...
        </saml2:Subject>
        ...
        <saml2:AttributeStatement>
            <saml2:Attribute Name="id">
                <saml2:AttributeValue ...>idp-id</saml2:AttributeValue>
            </saml2:Attribute>
        </saml2:AttributeStatement>
    </saml2:Assertion>
</saml2p:Response>

Attack path 2: abusing legitimate access for privilege escalation

There’s a variation of this attack that affects all service providers using xml-crypto, regardless of whether signed public metadata is available. However, it requires the attacker to have an identity in the identity provider and at least one provisioned app.

Attack path 2: abusing legitimate access for privilege escalation
  1. Attempt to log in to the service provider using either the IdP or SP-initiated flows
  2. Intercept the request to the ACS URL containing the SAML response
  3. Modify the SAML assertion as needed
  4. Recalculate the SAML assertion digest and insert the new digest value as a comment in the SAML Signature DigestValue node
  5. Replace the SAML response in the request with your crafted SAML response
  6. Forward the request to ACS URL
  7. The service provider validates the response, and you’ve authenticated

Breaking the chain of trust: How xml-crypto fails

This section explains the root cause of the vulnerability within the xml-crypto library. Readers may note the presence of a common pattern in security vulnerabilities, where two components of a system disagree on how to interpret the same data.

For a SAML service provider to securely trust an assertion in a SAML response, it must validate the IdP’s cryptographic signature. This chain of trust starts with the IdP’s X.509 certificate, extends to the signature over a SignedInfo block, includes the assertion digest within SignedInfo, and ultimately ends with the assertion itself.

The diagram below illustrates how the chain of trust is broken in the SAMLStorm attack.

How SAMLStorm breaks the chain of trust

In the xml-crypto library, the assertion digest check ensures that the digest in the SignedInfo block correctly corresponds to the assertion, while the signature check verifies that the signature is valid based on the IdP’s certificate and the SignedInfo block. In normal operation, the signature protects an assertion from modification, because the assertion digest is included in the SignedInfo block.

The core issue in this vulnerability is that these two checks evaluate the SAML document differently. SAML documents undergo canonicalization, a process that removes XML comments. However, the assertion digest checks are performed on the non-canonicalized document (which retains comments), while the signature checks are performed on the canonicalized document (which strips comments). This mismatch creates an opportunity for exploitation via the insertion of a forged digest inside a comment, as shown below.

<DigestValue><!-- forged_digest -->legitimate_digest</DigestValue>

In the vulnerable code, the SAML assertion digest check retrieves the first child of the DigestValue node. Normally, this is the expected digest value, but an attacker can insert an XML comment containing a forged digest of their own arbitrary assertion before the legitimate digest. As a result, the assertion digest check mistakenly uses the attacker’s digest.

Meanwhile, the signature check is performed on the SignedInfo block after it has been canonicalized. Since the malicious comment is stripped during canonicalization, only the original (legitimate) assertion digest remains, allowing the signature check to pass.

This breaks the chain of trust between the certificate and the assertion, enabling an attacker to forge arbitrary assertions that a vulnerable service provider will accept as valid.

Understanding if your application may be impacted

Any customer of a service provider using a vulnerable version of the xml-crypto library is at risk, though the level of risk depends on the specific service provider and whether the threat actor has an identity within an identity provider (IdP). If the attacker has an identity from any IdP connected to the service provider, they can exploit this vulnerability against any SAML identity provider, as long as the service provider relies on xml-crypto.

If the threat actor does not have an identity within the IdP, they can still exploit this vulnerability—but only against identity providers that sign their provider metadata. Many major IdPs sign their provider metadata. While this is not a security vulnerability in these identity providers, it does expose information that an attacker could leverage to exploit the bug in xml-crypto.

If an application does not independently verify account ownership, a threat actor could forge authentication for any user within an organization, including admin users, and escalate privileges using SAML attributes or IdP group assignments. Additionally, if an application does not restrict which users an IdP is allowed to authenticate, an attacker could forge authentication for any user in the service provider’s application, regardless of organization boundaries.

Recommendations for impacted organizations

Short-term recommendations

For companies

WorkOS has already patched this vulnerability and confirmed that no systems or customers were affected. However, other non-WorkOS auth systems may still be at risk. We recommend the following steps:

  1. Contact any applications where you authenticate via SAML SSO to ask if they were impacted and what risk remains.
  2. Review audit logs in affected applications for any suspicious logins or activity.

For service providers

  1. Check if your SAML implementation uses the xml-crypto package.
  2. If it does, review your SAML logs for signs of exploitation. Specifically, look for comments embedded in the DigestValue field of the response, for example:
<DigestValue><!-- forged_digest -->legitimate_digest</DigestValue>

Long-term recommendations

For companies

  1. Regularly review your organization’s exposure to applications protected by SSO, and keep an up-to-date inventory of all such vendors, with security contact information for and notes about the type of data stored by each.
  2. Choose vendors that support fully-featured security audit logging capabilities so you can independently review access to your data as needed.

For service providers

  1. Ensure tenants secured by SSO are properly isolated with principle of least privilege applied to IdP’s. For example, WorkOS mitigates cross-tenant access by default by supporting per-organization restrictions on identity domains.
  2. In general, checking that received data conforms to basic expectations before processing it serves as a valuable defense-in-depth mechanism against unknown vulnerabilities. Consider applying this principle to SAML responses to ensure their structure matches what is expected, especially for the certificates, signatures, and digests involved in the chain of trust. For example, node-saml was unaffected by the exploitation vector in CVE-2025-29774 because it checks whether the number of references in the SignedInfo block matches the expected value of one before passing the response to xml-crypto for further validation.

WorkOS' rapid response timeline:

  • March 4 – Report received, immediate triage
  • March 5 – Full patch deployed, customers secured
  • March 6 – Industry-wide notifications sent to identity and auth vendors
  • March 14 – Public disclosure

We would like to thank Alexander Tan (ahacker1) for his responsible disclosure and collaboration with the WorkOS Security Team. Special thanks also to GitHub Security Lab, Latacora, and Chris Barth (maintainer of node-saml) for their contributions.

WorkOS is committed to proactive security and rapid response and was the first company to detect, patch, and disclose SAMLStorm. We continue leading in securing authentication infrastructure for customers including OpenAI, Cursor, Perplexity, Vercel, Plaid, and hundreds more. If you have a security report to share, please contact security@workos.com.

This site uses cookies to improve your experience. Please accept the use of cookies on this site. You can review our cookie policy here and our privacy policy here. If you choose to refuse, functionality of this site will be limited.