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.

NAME

Net::SAML2::XML::Sig - Net::SAML2::XML::Sig - A toolkit to help sign and verify XML Digital Signatures

VERSION

version 0.45

SYNOPSIS

my $xml = '<foo ID="abc">123</foo>';
my $signer = Net::SAML2::XML::Sig->new({
  key => 'path/to/private.key',
});

# create a signature
my $signed = $signer->sign($xml);
print "Signed XML: $signed\n";

# verify a signature
$signer->verify($signed)
  or die "Signature Invalid.";
print "Signature valid.\n";

DESCRIPTION

This perl module provides two primary capabilities: given an XML string, create and insert digital signatures, or if one is already present in the string verify it -- all in accordance with the W3C standard governing XML signatures.

NAME

Net::SAML2::XML::Sig - A toolkit to help sign and verify XML Digital Signatures.

PREREQUISITES

USAGE

SUPPORTED ALGORITHMS & TRANSFORMS

This module supports the following signature methods:

  • DSA

  • RSA

  • RSA encoded as x509

  • ECDSA

  • ECDSA encoded as x509

This module supports the following canonicalization methods and transforms:

  • Enveloped Signature

  • REC-xml-c14n-20010315#

  • REC-xml-c14n-20010315#WithComments

  • REC-xml-c14n11-20080502

  • REC-xml-c14n11-20080502#WithComments

  • xml-exc-c14n#

  • xml-exc-c14n#WithComments

OPTIONS

Each of the following options are also accessors on the main Net::SAML2::XML::Sig object. TODO Not strictly correct rewrite

key

The path to a file containing the contents of a private key. This option is used only when generating signatures.

cert

The path to a file containing a PEM-formatted X509 certificate. This option is used only when generating signatures with the "x509" option. This certificate will be embedded in the signed document, and should match the private key used for the signature.

cert_text

A string containing a PEM-formatted X509 certificate. This option is used only when generating signatures with the "x509" option. This certificate will be embedded in the signed document, and should match the private key used for the signature.

x509

Takes a true (1) or false (0) value and indicates how you want the signature to be encoded. When true, the X509 certificate supplied will be encoded in the signature. Otherwise the native encoding format for RSA, DSA and ECDSA will be used.

sig_hash

Passing sig_hash to new allows you to specify the SignatureMethod hashing algorithm used when signing the SignedInfo. RSA and ECDSA supports the hashes specified sha1, sha224, sha256, sha384 and sha512

DSA supports only sha1 and sha256 (but you really should not sign anything with DSA anyway).

digest_hash

Passing digest_hash to new allows you to specify the DigestMethod hashing algorithm used when calculating the hash of the XML being signed. Supported hashes can be specified sha1, sha224, sha256, sha384, and sha512

no_xml_declaration

Some applications such as Net::SAML2 expect to sign a fragment of the full XML document so is this is true (1) it will not include the XML Declaration at the beginning of the signed XML. False (0) or undefined returns an XML document starting with the XML Declaration.

METHODS

new(...)

Constructor; see OPTIONS above.

sign($xml)

When given a string of XML, it will return the same string with a signature generated from the key provided when the Net::SAML2::XML::Sig object was initialized.

This method will sign all elements in your XML with an ID (case sensitive) attribute. Each element with an ID attribute will be the basis for a seperate signature. It will correspond to the URI attribute in the Reference element that will be contained by the signature. If no ID attribute can be found on an element, the signature will not be created.

The elements are signed in reverse order currently assuming (possibly incorrectly) that the lower element in the tree may need to be signed inclusive of its Signature because it is a child of the higher element.

Arguments: $xml: string XML string

Returns: string Signed XML

verify($xml)

Returns true or false based upon whether the signature is valid or not.

When using Net::SAML2::XML::Sig exclusively to verify a signature, no key needs to be specified during initialization given that the public key should be transmitted with the signature.

Net::SAML2::XML::Sig checks all signature in the provided xml and will fail should any signature pointing to an existing ID in the XML fail to verify.

Should there be a Signature included that does not point to an existing node in the XML it is ignored and other Signaures are checked. If there are no other Signatures it will return false.

Arguments: $xml: string XML string

Returns: string Signed XML

signer_cert()

Following a successful verify with an X509 certificate, returns the signer's certificate as embedded in the XML document for verification against a CA certificate. The certificate is returned as a Crypt::OpenSSL::X509 object.

Arguments: none

Returns: Crypt::OpenSSL::X509: Certificate used to sign the XML

ABOUT DIGITAL SIGNATURES

Just as one might want to send an email message that is cryptographically signed in order to give the recipient the means to independently verify who sent the email, one might also want to sign an XML document. This is especially true in the scenario where an XML document is received in an otherwise unauthenticated context, e.g. SAML.

However XML provides a challenge that email does not. In XML, two documents can be byte-wise inequivalent, and semanticaly equivalent at the same time. For example:

<?xml version="1.0"?>
<foo>
  <bar />
</foo>

And:

<?xml version="1.0"?>
<foo>
  <bar></bar>
</foo>

Each of these document express the same thing, or in other words they "mean" the same thing. However if you were to strictly sign the raw text of these documents, they would each produce different signatures.

XML Signatures on the other hand will produce the same signature for each of the documents above. Therefore an XML document can be written and rewritten by different parties and still be able to have someone at the end of the line verify a signature the document may contain.

There is a specially subscribed methodology for how this process should be executed and involves transforming the XML into its canonical form so a signature can be reliably inserted or extracted for verification. This module implements that process.

EXAMPLE SIGNATURE

Below is a sample XML signature to give you some sense of what they look like. First let's look at the original XML document, prior to being signed:

<?xml version="1.0"?>
<foo ID="abc">
  <bar>123</bar>
</foo>

Now, let's insert a signature:

<?xml version="1.0"?>
<foo ID="abc">
  <bar>123</bar>
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
      <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments" />
      <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
      <Reference URI="#abc">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
        <DigestValue>9kpmrvv3peVJpNSTRycrV+jeHVY=</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>
      HXUBnMgPJf//j4ihaWnaylNwAR5AzDFY83HljFIlLmTqX1w1C72ZTuRObvYve8TNEbVsQlTQkj4R
      hiY0pgIMQUb75GLYFtc+f0YmBZf5rCWY3NWzo432D3ogAvpEzYXEQPmicWe2QozQhybaz9/wrYki
      XiXY+57fqCkf7aT8Bb6G+fn7Aj8gnZFLkmKxwCdyGsIZOIZdQ8MWpeQrifxBR0d8W1Zm6ix21WNv
      ONt575h7VxLKw8BDhNPS0p8CS3hOnSk29stpiDMCHFPxAwrbKVL1kGDLaLZn1q8nNRmH8oFxG15l
      UmS3JXDZAss8gZhU7g9T4XllCqjrAvzPLOFdeQ==
    </SignatureValue>
    <KeyInfo>
      <KeyValue>
        <RSAKeyValue>
          <Modulus>
            1b+m37u3Xyawh2ArV8txLei251p03CXbkVuWaJu9C8eHy1pu87bcthi+T5WdlCPKD7KGtkKn9vq
            i4BJBZcG/Y10e8KWVlXDLg9gibN5hb0Agae3i1cCJTqqnQ0Ka8w1XABtbxTimS1B0aO1zYW6d+U
            Yl0xIeAOPsGMfWeu1NgLChZQton1/NrJsKwzMaQy1VI8m4gUleit9Z8mbz9bNMshdgYEZ9oC4bH
            n/SnA4FvQl1fjWyTpzL/aWF/bEzS6Qd8IBk7yhcWRJAGdXTWtwiX4mXb4h/2sdrSNvyOsd/shCf
            OSMsf0TX+OdlbH079AsxOwoUjlzjuKdCiFPdU6yAJw==
          </Modulus>
          <Exponent>Iw==</Exponent>
        </RSAKeyValue>
      </KeyValue>
    </KeyInfo>
  </Signature>
</foo>

SEE ALSO

http://www.w3.org/TR/xmldsig-core/

VERSION CONTROL

https://github.com/perl-net-saml2/perl-XML-Sig

AUTHORS and CREDITS

Author: Byrne Reese <byrne@majordojo.com>

Thanks to Manni Heumann who wrote Google::SAML::Response from which this module borrows heavily in order to create digital signatures.

Net::SAML2 embedded version amended by Chris Andrews <chris@nodnol.org>.

Maintainer: Timothy Legge <timlegge@cpan.org>

AUTHOR

Chris Andrews <chrisa@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2021 by Chris Andrews and Others, see the git log.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.