CVE-2026-55091 is a high-severity (CVSS 7.5) CWE-915 vulnerability in flat-to-nested. A fix is available for flat-to-nested — see the affected versions and patch details below.
flat-to-nested: Prototype pollution in flat-to-nested convert() via __proto__ parent/id key
Exploitation Status
No confirmed exploitation observed yet
- CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.
- CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.
Exploitation and automatability from CISA’s SSVC triage for CVE-2026-55091.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
How urgent is this, really
CVE-2026-55091 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.
Where this sits among everything scored
Of 395,249 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.
Real-World Exposure
How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.
flat-to-nestednpmDescription
Summary
convert() builds the nested tree by using each flat record's id and parent field values directly as object keys, with no guard against __proto__ / constructor / prototype. A record whose parent is the string "__proto__" makes temp[parent] resolve to Object.prototype, and the following initPush(...) writes attacker-controlled data onto the global prototype. Any application that passes attacker-influenced records to convert() is affected, and the base prototype methods stay intact so the pollution is stealthy.
Details
In index.js, convert() (FlatToNested.prototype.convert):
temp = {}(line 45) andpendingChildOf = {}(line 46) are plain objects, so they inherit fromObject.prototype.- For each record,
parent = flatEl[this.config.parent](line 51) is taken verbatim from input. - Line 57:
if (temp[parent] !== undefined)— whenparent === "__proto__",temp["__proto__"]resolves via the prototype chain toObject.prototype, which is!== undefined, so the branch is taken. - Line 59:
initPush(this.config.children, temp[parent], flatEl)→ effectivelyinitPush("children", Object.prototype, flatEl). initPush(lines 4-9):Object.prototype["children"] = []thenObject.prototype["children"].push(flatEl)— attacker-controlled data is written onto the globalObject.prototype.
There is no sanitization of id / parent anywhere; they flow straight into temp[id], temp[parent], and pendingChildOf[parent] as dynamic keys.
PoC
const FlatToNested = require('flat-to-nested');
new FlatToNested().convert([
{ id: 1, parent: '__proto__', polluted: 'PWNED' }
]);
console.log(({}).children); // => [ { id: 1, polluted: 'PWNED' } ]
A freshly-created, unrelated object {} now carries an attacker-controlled children property. ({}).toString === Object.prototype.toString remains true, so existing methods are untouched (stealthy). If the consumer configures a custom children key, that arbitrary prototype property is polluted instead.
Impact
Prototype pollution (CWE-1321). Any service that builds a tree from attacker-influenced flat records (the package's core purpose — e.g. records derived from a DB/REST/user input) can have Object.prototype polluted. Consequences range from application-logic corruption and denial of service to serving as a gadget toward privilege escalation or RCE depending on downstream sinks. No special privileges or user interaction required; the malicious value is ordinary input data.
Suggested fix
Use prototype-less lookup tables so inherited keys like proto cannot be reached: var temp = Object.create(null); var pendingChildOf = Object.create(null); (Optionally also reject id/parent values equal to proto, constructor, or prototype.) Verified: with Object.create(null) for both temp and pendingChildOf, the PoC no longer pollutes Object.prototype and normal nesting output is unchanged. A patch with a regression test is ready.
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 📦npm | flat-to-nested | all versions | 1.1.2npm install flat-to-nested@1.1.2 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for flat-to-nested, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update flat-to-nested to 1.1.2 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-55091 is resolved across your whole dependency graph.
Workarounds
Close the privilege gap rather than the entry point: audit which accounts, roles and service identities can reach the affected operation, drop the component to the least privilege it actually needs, and review file and directory permissions created by earlier installs — a default left in place is what makes this reachable.
Frequently Asked Questions
Is CVE-2026-55091 in your dependencies?
Find it across npm, including transitive dependencies.