CVE-2026-55091
Published:June 19, 2026
Updated:June 21, 2026
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) and "pendingChildOf = {}" (line 46) are plain objects, so they inherit from "Object.prototype". - For each record, "parent = flatEl[this.config.parent]" (line 51) is taken verbatim from input. - Line 57: "if (temp[parent] !== undefined)" — when "parent === "proto"", "temp["proto"]" resolves via the prototype chain to "Object.prototype", which is "!== undefined", so the branch is taken. - Line 59: "initPush(this.config.children, temp[parent], flatEl)" → effectively "initPush("children", Object.prototype, flatEl)". - "initPush" (lines 4-9): "Object.prototype["children"] = []" then "Object.prototype["children"].push(flatEl)" — attacker-controlled data is written onto the global "Object.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
https://github.com/joaonuno/flat-to-nested-js.git (GITHUB):
Affected version(s) >=v1.0.0 <v1.1.2Fix Suggestion:
Update to version v1.1.2flat-to-nested (NPM):
Affected version(s) >=0.0.1 <1.1.2Fix Suggestion:
Update to version 1.1.2Related Resources (3)
Do you need more information?
Contact UsCVSS v4
Base Score:
8.7
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
CVSS v3
Base Score:
7.5
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality
NONE
Integrity
HIGH
Availability
NONE