Security Advisories (3)
CVE-2026-18089 (2026-08-03)

Net::SAML2 versions before 0.86 for Perl allow SAML authentication bypass by verifying responses against the response-embedded certificate in verify_xml when no trust anchor is configured. verify_xml in Net::SAML2::Role::VerifyXML runs "return if !$anchors && !$cacert;" as soon as the XML::Sig check succeeds, and that check uses the X.509 certificate taken from the response's own dsig:KeyInfo/dsig:X509Certificate element, so an unanchored response is checked only against the key it carries. Binding::POST declares cacert as an optional Maybe[Str] with no default, so a POST binding built without one takes that path, and _verify_encrypted_assertion returns early the same way with "return $xml unless $cacert;". Any caller that constructs Binding::POST or calls Assertion->new_from_xml without a cacert, cert_text, or anchors argument accepts a response signed by an attacker generated key whose self-signed certificate is embedded in that response, authenticating an arbitrary assertion.

CVE-2026-18092 (2026-08-03)

Net::SAML2 versions before 0.86 for Perl allow SAML authentication bypass via XML signature wrapping because new_from_xml reads assertion identity with document-wide XPath instead of the signed subtree. new_from_xml reads the NameID, attribute values, SessionIndex, audience and other identity fields with document-wide XPath, such as //saml:Assertion/saml:AttributeStatement/saml:Attribute and //saml:Subject/saml:NameID, which select the first matching element in document order rather than the element covered by the verified signature. handle_response confirms that a signature is present and, when a cacert is configured, that it chains to the CA, but XML::Sig verifies only the element named by the signature's Reference URI, so unsigned sibling assertions in the same document are not covered. An attacker who holds any one IdP-signed assertion can add an unsigned attacker-authored assertion earlier in document order; the signature still verifies and the document-order XPath returns the attacker's NameID and attributes. Any caller that passes an untrusted Response to new_from_xml can accept identity fields from an assertion the IdP never signed, even when a cacert trust anchor is configured, so a party holding one valid IdP-signed assertion can authenticate as an arbitrary user.

CVE-2026-18108 (2026-08-03)

Net::SAML2 versions before 0.86 for Perl allow authentication bypass because _verify_encrypted_assertion accepts an EncryptedAssertion whose decrypted content carries no signature. _verify_encrypted_assertion decrypts the EncryptedAssertion and returns it as verified when it carries no signature, via "return $xml unless $xpath->exists('dsig:Signature', $assert);". The signature check and the trust anchor check that follow run only when a signature is present, so a decrypted assertion with no dsig:Signature element reaches new_from_xml unverified and its NameID and attributes are read into the assertion object. An SP's encryption certificate is published in its SAML metadata so the IdP can encrypt to it, so any party can encrypt an unsigned assertion to that certificate, wrap it in a samlp:Response, and post it to the assertion consumer service. Any caller that configures a decryption key_file, and so accepts EncryptedAssertions, takes identity fields from an assertion that no trust anchor covers, and an unauthenticated party can authenticate as an arbitrary user. Callers with no key_file configured do not decrypt and are unaffected.

Changes for version 0.60 - 2022-09-19

  • Significant Changes since 0.59
    • There are multiple potentially BREAKING CHANGES depending on how you have written your application. Your application may need updates for this version.
  • BREAKING CHANGES
    • Support multiple signing keys in the metadata. This version attempts to ensure compatibility but the call to Net::SAML2::IdP->cert will return an array of certs for each 'use'. It is, however, likely that there will only be one cert in the array.
    • Net::SAML2::Binding::SOAP was improved. The call to Net::SAML2::Binding::SOAP->handle_request() now returns the XML whereas in the past it returned the certificate's subject and the xml as an array. This make it consistent with the Redirect and POST Bindings.
    • Net::SAML2::Binding::POST was also improved. Previously the call to Net::SAML2::Binding::POST->handle_response() returned inconsistent results depending on whether a cacert was provided. This version returns the XML of the decoded request.
    • The testapp required only changes related to the call to Net::SAML2::IdP->cert($use) that now returns an ARRAY.
  • Changes of note:
    • Support multiple signing keys in the metadata. This version attempts to ensure compatability but the call to Net::SAML2::IdP->cert will return an array of certs for each $use. It is, however, likely that there will only be one cert in the array.
    • Redirects now validate the raw URI that is passed to the call. It is assumed that the URI that your application has sent is unmodified from the response that the web server received. lighttpd in particular normalizes the response and will break Redirects from Microsoft Azure (see lighttpd.conf in xt/testapp for a working configuration)
    • Net::SAML2::Binding::SOAP and Net::SAML2::Binding::POST were improved.
    • SAML trust anchors were implemented and the verification of the SAML response was improved. It is possible to validate the response with subject, issuer or issuer_hash as anchors in addition to the cacert. Neither cacert nor anchors are required as long as the signature of the response is valid. The cacert has not been required for the Redirect or SOAP binding so this treats SOAP the same.
  • Required Application Updates
    • There were several changed to the test suite that will likely need to be made in your application:
    • To support metadata.xml containing multiple KeyDescriptors the call to Net::SAML2::IdP->cert($use) now returns an ARRAY. As this is an helper function that is meant to allow you to pass the cert to another Net::SAML2 call it was deemed low risk. Your code may be unaffected.
    • The call to Net::SAML2::Binding::SOAP->handle_request() needs to be updated to reflect that it returns only the decoded XML not an array of the Certificate Subject and XML. Depending how your application uses the response will determine whether changes are required.
    • The call to Net::SAML2::Binding::POST->handle_response() returned inconsistent results depending on whether a cacert was provided. This version returns the XML of the decoded request. Previously it returned either 1 for success or if a cacert was used, either "(verified) and the certificate Subject" or 0 if the certificate verification failed.
    • The lighttpd.conf for the testapp did require a change to prevent it from "normalizing" a SAML Logout Redirect. There are contradictory RFCs concerning SAML and the "normalising" URIs. If you use lighttpd in a SAML application with AZURE as your SAML IdP see [lighttpd.conf](https://github.com/perl-net-saml2/perl-Net-SAML2/commit/3855393eb454097e1e326a516a573f37ce3456a3#diff-8fd15aaa870fd2b9cda596bf3bb870ce2723ae412e55f0b653124b45d87e1bea)
  • Possible Impacts
    • It is worth noting that the testapp (that implements a rudimentary Service Provider) included in the git repo did not require any changes to the application for this version.
    • While my setup tests against multiple IdPs I do not have a working SOAP IdP at present.
  • Full Change Log
    • e95e7c2 Fix bug where two keys with different usage fails
    • 33092f1 Add isDefault when isDefault is missing in assertion_consumer_service
    • 66a4146 Bump version to .60
    • 812ea36 0.59 updates
    • f589dd0 v0.59
    • c1b25f9 Sync changes with the wiki page and clean up indents
    • 2c432f2 Remove unnecessary parameters
    • 3855393 Allow URIs that do not include scheme and host in redirect
    • e1774b6 Update docs for Net::SAML2::Protocol::LogoutRequest
    • fdcfbeb Fix docs for Net::SAML2::Binding::Redirect
    • 8d24c89 Update docs for Net::SAML2::Protocol::ArtifactResolve
    • 27f6508 Update docs for Net::SAML::SP
    • 4a89679 Fix docs for Net::SAML2::Binding::SOAP
    • f43727d Verify the SAMLResponse based on the raw query string
    • 50f5c8a Fixes #12 - multiple signing keys in metadata
    • 4902c89 Make SAML trust anchors work on verification of the SAML request
    • af68b68 SOAP binding does not require a cacert anymore
    • 1854e35 Implement verify_xml() call which only verifies the XML

Documentation

Modules

SAML2 bindings and protocol implementation
Net::SAML2::Binding::POST - HTTP POST binding for SAML
Net::SAML2::Binding::Redirect - HTTP Redirect binding for SAML
Net::SAML2::Binding::SOAP - SOAP binding for SAML
Net::SAML2::IdP - SAML Identity Provider object
Net::SAML2::Protocol::ArtifactResolve - ArtifactResolve protocol class
Net::SAML2::Protocol::Assertion - SAML2 assertion object
SAML2 AuthnRequest object
SAML2 LogoutRequest Protocol object
SAML2 LogoutResponse Protocol object
Common behaviour for Protocol messages
A role to verify the SAML response XML
Net::SAML2::SP - SAML Service Provider object
Custom Moose types for Net::SAML2
Utility functions for Net::SAML2
Net::SAML2 subclass of XML::Sig
Net::SAML2::XML::Util - XML Util class