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::Binding::Redirect - HTTP Redirect binding for SAML

VERSION

version 0.84

SYNOPSIS

my $redirect = Net::SAML2::Binding::Redirect->new(
  key     => '/path/to/SPsign-nopw-key.pem',		# Service Provider (SP) private key
  url     => $sso_url,							# Service Provider Single Sign Out URL
  param   => 'SAMLRequest' OR 'SAMLResponse',		# Type of request
  cert    => $idp->cert('signing')				# Identity Provider (IdP) certificate
  sig_hash => 'sha256', 'sha224', 'sha384', 'sha512' or 'sha1'  # Signature to sign request
);

my $url = $redirect->sign($authnreq);

my $ret = $redirect->verify($url);

METHODS

new( ... )

Constructor. Creates an instance of the Redirect binding.

Arguments:

key

The SP's (Service Provider) also known as your application's signing key that your application uses to sign the AuthnRequest. Some IdPs may not verify the signature.

Usually required when param is SAMLRequest.

If you don't want to sign the request, you can pass insecure => 1 and not provide a key; in this case, sign will return a non-signed URL.

cert

IdP's (Identity Provider's) certificate that is used to verify a signed Redirect from the IdP. It is used to verify the signature of the Redirect response. Required with param being SAMLResponse.

url

IdP's SSO (Single Sign Out) service url for the Redirect binding Required with param being SAMLRequest.

param

query param name to use (SAMLRequest, SAMLResponse) Defaults to SAMLRequest.

sig_hash

RSA signature hash used to sign request

Supported:

sha256, sha224, sha384, sha512 and sha1

Defaults to sha256.

debug

Output extra debugging information

get_redirect_uri($authn_request, $relaystate)

Get the redirect URI for a given request, and returns the URL to which the user's browser should be redirected.

Accepts an optional RelayState parameter, a string which will be returned to the requestor when the user returns from the authentication process with the IdP.

The request is signed unless the the object has been instantiated with <insecure = 1>>.

sign( $request, $relaystate )

Signs the given request, and returns the URL to which the user's browser should be redirected.

Accepts an optional RelayState parameter, a string which will be returned to the requestor when the user returns from the authentication process with the IdP.

Returns the signed (or unsigned) URL for the SAML2 redirect

verify( $query_string )

my ($request, $relaystate) = $self->verify($query_string)

Decode a Redirect binding URL.

Verifies the signature on the response.

Requires the *raw* query string to be passed, because URI parses and re-encodes URI-escapes in uppercase (%3f becomes %3F, for instance), which leads to signature verification failures if the other party uses lower case (or mixed case).

Returns an ARRAY of containing the verified request and relaystate (if it exists). Croaks on errors.

AUTHOR

Timothy Legge <timlegge@gmail.com>

COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by Venda Ltd, see the CONTRIBUTORS file for others.

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