Originally published at HOL
CVE-2026-18108: Net::SAML2 Authentication Bypass via Unsigned Encrypted Assertions (CVSS 9.8)
TL;DR: Net::SAML2, the dominant Perl SAML library, accepts decrypted SAML assertions that carry no XML digital signature. An attacker who knows an SP's public encryption key (published in SAML metadata) can encrypt a forged assertion with an arbitrary NameID, wrap it in a samlp:Response, and post it to the assertion consumer service. No credentials. No interaction. Complete identity spoof. CVSS 9.8. Fixed in version 0.86.
What is Net::SAML2
Net::SAML2 is the primary Perl library for implementing SAML 2.0 Service Providers. It handles the full Web Browser SSO profile: AuthnRequest generation, SAML response parsing, encrypted assertion decryption, XML signature verification, and trust anchor validation. It is the SAML backbone for Perl-based identity systems.
The library is explicitly tested against every major identity provider: Azure AD (Microsoft Office 365), Google GSuite, Okta, OneLogin, Microsoft ADFS, PingIdentity, Shibboleth, Keycloak, Auth0, and SimpleSAMLphp. It also supports government identity systems including DigiD (Netherlands), eHerkenning, and eIDAS. This breadth means Net::SAML2 sits in front of university portals, government services, healthcare systems, and corporate SSO deployments.
Any Perl application that configures a decryption key_file and accepts EncryptedAssertions is affected. Callers who do not set a key_file and do not decrypt are unaffected.
How big is the impact
The CVSS 9.8 vector (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) captures the severity: network-exploitable, no privileges, no user interaction, full confidentiality and integrity compromise. The attack requires one piece of public information: the SP's encryption certificate, which is published in the SP's SAML metadata by design (the IdP needs it to encrypt assertions to the SP).
An attacker constructs a SAML response containing an EncryptedAssertion that decrypts to an unsigned assertion with a forged NameID. Net::SAML2 decrypts it, finds no dsig:Signature element, and returns it as verified. The trust anchor check never executes. The attacker authenticates as any user in the system: an administrator, a CEO, a customer with privileged access. The attack leaves no obvious trace because it arrives through the normal SAML POST endpoint.
This is not a theoretical concern. SAML is the authentication protocol for thousands of enterprise applications. A single vulnerable SP behind Azure AD or Okta gives the attacker a door into the entire SSO ecosystem.
What happened
The vulnerability is in _verify_encrypted_assertion in the Assertion protocol class. The method decrypts the EncryptedAssertion and then checks whether the decrypted XML contains a dsig:Signature element. If no signature is present, it returns the XML as verified via return $xml unless $xpath->exists('dsig:Signature', $assert);. The signature check and trust anchor validation run only when a signature exists.
The fix in version 0.86 ensures that decrypted assertions without a signature are rejected rather than silently accepted. The commit (d916468) adds a check that requires either a dsig:Signature or a rejection. The changelog in 0.86 documents the change: "Do not accept unsigned assertions as verified when they arrive in EncryptedAssertion form."
What to do
Update Net::SAML2 to version 0.86:
cpanm Net::SAML2@0.86
If you cannot update immediately, disable EncryptedAssertion support by removing any key_file configuration. This forces the SP to reject encrypted assertions entirely. Audit your SAML consumer logs for POST requests with unusual or unexpected NameID fields, particularly for administrative user identifiers. If your SP publishes its metadata publicly, rotate your encryption certificate after patching.
Top comments (0)