Skip to main content

flat-to-nested CVE-2026-55091

HIGH
Improperly Controlled Modification of Dynamically-Determined Object Attributes (CWE-915)
2026-06-19 https://github.com/joaonuno/flat-to-nested-js GHSA-hp36-v28f-w3r4
7.5
CVSS 3.1 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
7.5 HIGH
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N
vuln.today AI
8.2 HIGH

Library is typically reached via network-fed records with no auth or interaction; integrity is high (arbitrary prototype writes), with low availability impact from likely logic crashes and no direct confidentiality loss.

3.1 AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:L
4.0 AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:L/SC:N/SI:N/SA:N

Primary rating from GitHub Advisory.

CVSS VectorGitHub Advisory

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
High
Availability
None

Lifecycle Timeline

2
Source Code Evidence Fetched
Jun 19, 2026 - 21:38 vuln.today
Analysis Generated
Jun 19, 2026 - 21:38 vuln.today

Blast Radius

ecosystem impact
† from your stack dependencies † transitive graph · vuln.today resolves 4-path depth
  • 89 npm packages depend on flat-to-nested (11 direct, 80 indirect)

Ecosystem-wide dependent count for version 1.1.2.

DescriptionGitHub Advisory

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

js
  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.

AnalysisAI

Prototype pollution in the npm package flat-to-nested (versions <= 1.1.1) lets attackers who control input records pollute Object.prototype by supplying a record with parent set to the string '__proto__'. The convert() function uses plain objects as lookup tables and writes attacker-controlled data through the prototype chain via initPush(), affecting any application that feeds untrusted flat records (REST input, DB rows, user-supplied data) into the library. …

Unlock full vulnerability intelligence

  • Risk assessment & exploitation conditions
  • Attack chain visualization
  • Remediation with exact patch versions
  • Threat intelligence from 22 sources
  • Personal watchlist & email alerts

Free forever · No credit card required

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata

Access
Identify endpoint feeding convert()
Delivery
Submit record with parent='__proto__'
Exploit
Trigger temp['__proto__'] prototype lookup
Execution
initPush writes to Object.prototype
Persist
Subsequent code reads polluted property
Impact
Logic bypass or downstream RCE gadget

Vulnerability AssessmentAI

Exploitation The consuming application must call FlatToNested.prototype.convert() on records whose parent or id field is attacker-influenced (typical for the library's documented purpose - building trees from user, REST, or database input). … Additional conditions and limiting factors are described in the full assessment.
Risk Assessment The CVSS 3.1 vector AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N (7.5 High) reflects integrity-only impact reachable over the network without authentication or interaction, which matches the library's use as a data-shaping utility in web back-ends. … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in.
Exploit Scenario A Node.js service exposes an endpoint that ingests JSON records (for example, a hierarchical category import or org-chart upload) and passes them to flat-to-nested's convert() to build a tree. An attacker submits a record like {id: 1, parent: '__proto__', isAdmin: true}; after the call, every newly created plain object in the process inherits an attacker-controlled property, which a downstream check such as if (user.isAdmin) or a templating engine's option merge can then honor - escalating from data corruption to authorization bypass or RCE depending on the gadget. …
Remediation Vendor-released patch: upgrade flat-to-nested to 1.1.2 or later, which replaces the plain-object lookup tables with Object.create(null) so that '__proto__', 'constructor', and 'prototype' become harmless own keys rather than prototype-chain references (commit 680a5ebe1194edda16fa93baaa56ff14fe0e3d7f, advisory GHSA-hp36-v28f-w3r4). … Detailed patch versions, workarounds, and compensating controls in full report.

Recommended ActionAI

Within 24 hours: Inventory all applications using flat-to-nested <= 1.1.1 and identify those processing untrusted input (APIs, file uploads, user submissions). …

Sign in for detailed remediation steps and compensating controls.

Threat intelligence, references, and detailed analysis are available after sign-in.

Share

CVE-2026-55091 vulnerability details – vuln.today

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