{"id":"CVE-2026-55091","aliases":["EUVD-2026-77691","GHSA-hp36-v28f-w3r4"],"status":"published","title":"flat-to-nested: Prototype pollution in flat-to-nested convert() via __proto__ parent/id key","description":"flat-to-nested converts a hierarchy from a flat representation to a nested representation. Prior to 1.1.2, FlatToNested.prototype.convert in index.js uses attacker-influenced id and parent record fields directly as keys in the plain temp and pendingChildOf objects. When parent or id is __proto__, temp[parent] can resolve to Object.prototype, and initPush() can write attacker-controlled data to the global children prototype property while existing prototype methods remain intact. Any application that passes attacker-influenced flat records to convert() can therefore expose unrelated objects to polluted inherited state, causing application-logic corruption or denial of service and potentially enabling greater impact when a downstream prototype-pollution gadget is present. The constructor and prototype strings are also unsafe inherited-key values in the same lookup design. This issue is fixed in version 1.1.2.","severity":{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-10","score":0.00497,"percentile":0.42969,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-1321","CWE-915"],"published":"2026-06-19T20:47:52Z","modified":"2026-10-28T02:31:11Z","fixes":[{"ecosystem":"npm","package":"flat-to-nested","fixed_in":["1.1.2"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"flat-to-nested","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"1.1.1"},{"fixed":"1.1.2"}]}]},{"source":"osv","ecosystem":"npm","package":"flat-to-nested","ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"1.1.2"}]}]}],"products":[{"vendor":"joaonuno","product":"flat-to-nested-js"}],"references":[{"url":"https://github.com/joaonuno/flat-to-nested-js/security/advisories/GHSA-hp36-v28f-w3r4","tags":["x_refsource_CONFIRM","advisory","web"]},{"url":"https://github.com/joaonuno/flat-to-nested-js/commit/680a5ebe1194edda16fa93baaa56ff14fe0e3d7f","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/joaonuno/flat-to-nested-js/releases/tag/v1.1.2","tags":["x_refsource_MISC","web"]},{"url":"https://github.com/advisories/GHSA-hp36-v28f-w3r4"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/55xxx/CVE-2026-55091.json","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-55091","tags":["advisory"]},{"url":"https://github.com/joaonuno/flat-to-nested-js","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-55091","title":"flat-to-nested: Prototype pollution in flat-to-nested convert() via __proto__ parent/id key","description":"flat-to-nested converts a hierarchy from a flat representation to a nested representation. Prior to 1.1.2, FlatToNested.prototype.convert in index.js uses attacker-influenced id and parent record fields directly as keys in the plain temp and pendingChildOf objects. When parent or id is __proto__, temp[parent] can resolve to Object.prototype, and initPush() can write attacker-controlled data to the global children prototype property while existing prototype methods remain intact. Any application that passes attacker-influenced flat records to convert() can therefore expose unrelated objects to polluted inherited state, causing application-logic corruption or denial of service and potentially enabling greater impact when a downstream prototype-pollution gadget is present. The constructor and prototype strings are also unsafe inherited-key values in the same lookup design. This issue is fixed in version 1.1.2.","status":"published","published":"2026-09-14T17:26:38.877Z","modified":"2026-09-14T20:05:59.07Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high","assessor":"cna"}],"cwes":["CWE-915","CWE-1321"],"updated_at":"2026-11-02T14:20:11.925815Z"}],"euvd":[{"id":"EUVD-2026-77691","description":"flat-to-nested converts a hierarchy from a flat representation to a nested representation. Prior to 1.1.2, FlatToNested.prototype.convert in index.js uses attacker-influenced id and parent record fields directly as keys in the plain temp and pendingChildOf objects. When parent or id is __proto__, temp[parent] can resolve to Object.prototype, and initPush() can write attacker-controlled data to the global children prototype property while existing prototype methods remain intact. Any application that passes attacker-influenced flat records to convert() can therefore expose unrelated objects to polluted inherited state, causing application-logic corruption or denial of service and potentially enabling greater impact when a downstream prototype-pollution gadget is present. The constructor and prototype strings are also unsafe inherited-key values in the same lookup design. This issue is fixed in version 1.1.2.","status":"published","published":"2026-09-14T17:26:38Z","modified":"2026-09-14T20:05:59Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high"}],"updated_at":"2026-11-02T17:28:19.383429Z"}],"ghsa":[{"id":"GHSA-hp36-v28f-w3r4","title":"flat-to-nested: Prototype pollution in flat-to-nested convert() via __proto__ parent/id key","description":"### Summary\n  `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.\n\n  ### Details\n  In `index.js`, `convert()` (`FlatToNested.prototype.convert`):\n\n  - `temp = {}` (line 45) and `pendingChildOf = {}` (line 46) are plain objects, so they inherit from `Object.prototype`.\n  - For each record, `parent = flatEl[this.config.parent]` (line 51) is taken verbatim from input.\n  - Line 57: `if (temp[parent] !== undefined)` — when `parent === \"__proto__\"`, `temp[\"__proto__\"]` resolves via the prototype chain to `Object.prototype`, which is `!== undefined`, so the\n  branch is taken.\n  - Line 59: `initPush(this.config.children, temp[parent], flatEl)` → effectively `initPush(\"children\", Object.prototype, flatEl)`.\n  - `initPush` (lines 4-9): `Object.prototype[\"children\"] = []` then `Object.prototype[\"children\"].push(flatEl)` — **attacker-controlled data is written onto the global `Object.prototype`.**\n\n  There is no sanitization of `id` / `parent` anywhere; they flow straight into `temp[id]`, `temp[parent]`, and `pendingChildOf[parent]` as dynamic keys.\n\n  ### PoC\n  ```js\n  const FlatToNested = require('flat-to-nested');\n\n  new FlatToNested().convert([\n    { id: 1, parent: '__proto__', polluted: 'PWNED' }\n  ]);\n\n  console.log(({}).children); // =\u003e [ { id: 1, polluted: 'PWNED' } ]\n  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.\n ```\n \n  ### Impact\n\n  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.\n\n  ### Suggested fix\n\n  Use prototype-less lookup tables so inherited keys like __proto__ cannot be reached:\n  var temp = Object.create(null);\n  var pendingChildOf = Object.create(null);\n  (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.","status":"published","published":"2026-06-19T20:47:52Z","modified":"2026-06-19T20:47:54Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high"}],"cwes":["CWE-915","CWE-1321"],"updated_at":"2026-11-02T14:40:31.656952Z"}],"nvd":[{"id":"CVE-2026-55091","description":"flat-to-nested converts a hierarchy from a flat representation to a nested representation. Prior to 1.1.2, FlatToNested.prototype.convert in index.js uses attacker-influenced id and parent record fields directly as keys in the plain temp and pendingChildOf objects. When parent or id is __proto__, temp[parent] can resolve to Object.prototype, and initPush() can write attacker-controlled data to the global children prototype property while existing prototype methods remain intact. Any application that passes attacker-influenced flat records to convert() can therefore expose unrelated objects to polluted inherited state, causing application-logic corruption or denial of service and potentially enabling greater impact when a downstream prototype-pollution gadget is present. The constructor and prototype strings are also unsafe inherited-key values in the same lookup design. This issue is fixed in version 1.1.2.","status":"published","published":"2026-09-14T18:17:54.79Z","modified":"2026-09-30T17:51:56.193Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high","assessor":"secondary"}],"cwes":["CWE-915","CWE-1321"],"updated_at":"2026-11-02T14:12:46.980627Z"}],"osv":[{"id":"CVE-2026-55091","title":"flat-to-nested: Prototype pollution in flat-to-nested convert() via __proto__ parent/id key","description":"flat-to-nested converts a hierarchy from a flat representation to a nested representation. Prior to 1.1.2, FlatToNested.prototype.convert in index.js uses attacker-influenced id and parent record fields directly as keys in the plain temp and pendingChildOf objects. When parent or id is __proto__, temp[parent] can resolve to Object.prototype, and initPush() can write attacker-controlled data to the global children prototype property while existing prototype methods remain intact. Any application that passes attacker-influenced flat records to convert() can therefore expose unrelated objects to polluted inherited state, causing application-logic corruption or denial of service and potentially enabling greater impact when a downstream prototype-pollution gadget is present. The constructor and prototype strings are also unsafe inherited-key values in the same lookup design. This issue is fixed in version 1.1.2.","status":"published","published":"2026-09-14T17:26:38.877Z","modified":"2026-10-28T02:31:11.897932515Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high"}],"cwes":["CWE-1321","CWE-915"],"updated_at":"2026-11-02T15:45:11.22012Z"},{"id":"GHSA-hp36-v28f-w3r4","title":"flat-to-nested: Prototype pollution in flat-to-nested convert() via __proto__ parent/id key","description":"### Summary\n  `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.\n\n  ### Details\n  In `index.js`, `convert()` (`FlatToNested.prototype.convert`):\n\n  - `temp = {}` (line 45) and `pendingChildOf = {}` (line 46) are plain objects, so they inherit from `Object.prototype`.\n  - For each record, `parent = flatEl[this.config.parent]` (line 51) is taken verbatim from input.\n  - Line 57: `if (temp[parent] !== undefined)` — when `parent === \"__proto__\"`, `temp[\"__proto__\"]` resolves via the prototype chain to `Object.prototype`, which is `!== undefined`, so the\n  branch is taken.\n  - Line 59: `initPush(this.config.children, temp[parent], flatEl)` → effectively `initPush(\"children\", Object.prototype, flatEl)`.\n  - `initPush` (lines 4-9): `Object.prototype[\"children\"] = []` then `Object.prototype[\"children\"].push(flatEl)` — **attacker-controlled data is written onto the global `Object.prototype`.**\n\n  There is no sanitization of `id` / `parent` anywhere; they flow straight into `temp[id]`, `temp[parent]`, and `pendingChildOf[parent]` as dynamic keys.\n\n  ### PoC\n  ```js\n  const FlatToNested = require('flat-to-nested');\n\n  new FlatToNested().convert([\n    { id: 1, parent: '__proto__', polluted: 'PWNED' }\n  ]);\n\n  console.log(({}).children); // =\u003e [ { id: 1, polluted: 'PWNED' } ]\n  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.\n ```\n \n  ### Impact\n\n  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.\n\n  ### Suggested fix\n\n  Use prototype-less lookup tables so inherited keys like __proto__ cannot be reached:\n  var temp = Object.create(null);\n  var pendingChildOf = Object.create(null);\n  (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.","status":"published","published":"2026-06-19T20:47:52Z","modified":"2026-06-19T21:11:28.86403Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N","level":"high"}],"cwes":["CWE-1321","CWE-915"],"updated_at":"2026-11-02T15:46:49.28217Z"}]}}
