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: ```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(
- Products
- toml
- Affected versions
- Not specified
- Fixed versions
- 5.0.1
- CVEs
- CVE-2026-114142
- Confirmed fixed CVEs
- Not specified
- Updated in this feed
- 1 Nov 2026, 14:48 UTC · Revision 1
Source evidence
toml-node: Prototype pollution: parsing a TOML document can write to Object.prototype
core-osv · Original sourcePublished 22 Oct 2026, 16:39 UTC
### 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(
osv:GHSA-h895-cgqg-jf52
toml
Fixed versions: 5.0.1
Complete source record
{
"id": "7dd442df13b6a276b28a2aa0c9be86848eb1957202436083db001a199ba1f26a",
"url": "https://osv.dev/vulnerability/GHSA-h895-cgqg-jf52",
"method": "structured",
"payload": {
"kind": "advisory",
"title": "toml-node: Prototype pollution: parsing a TOML document can write to Object.prototype",
"summary": "### 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(",
"evidence": "osv:GHSA-h895-cgqg-jf52",
"products": [
{
"name": {
"value": "toml",
"evidence": "/affected/0/package/name"
},
"prerequisites": [],
"fixed_versions": [
{
"value": "5.0.1",
"evidence": "/affected/0/ranges"
}
],
"affected_versions": []
}
],
"severity": "high",
"structured": {
"id": "GHSA-h895-cgqg-jf52",
"aliases": [
"CVE-2026-114142",
"GHSA-h895-cgqg-jf52"
],
"metrics": [
{
"type": "CVSS_V4",
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N"
}
],
"affected": [
{
"ranges": [
{
"type": "SEMVER",
"events": [
{
"introduced": "0"
},
{
"fixed": "5.0.1"
}
]
}
],
"package": {
"name": "toml",
"purl": "pkg:npm/toml",
"ecosystem": "npm"
},
"database_specific": {
"source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-h895-cgqg-jf52/GHSA-h895-cgqg-jf52.json",
"last_known_affected_version_range": "<= 5.0.0"
}
}
],
"modified": "2026-10-26T14:45:05.681971920Z",
"provider": "osv",
"references": [
"https://github.com/BinaryMuse/toml-node/security/advisories/GHSA-h895-cgqg-jf52",
"https://nvd.nist.gov/vuln/detail/CVE-2026-114142",
"https://github.com/BinaryMuse/toml-node/commit/609c873fffea0a27ebe5b4dd098eed2b3daf3606",
"https://github.com/BinaryMuse/toml-node",
"https://github.com/BinaryMuse/toml-node/releases/tag/v5.0.1"
],
"provider_metadata": {
"cwe_ids": [
"CWE-1321"
],
"severity": "HIGH",
"github_reviewed": true,
"nvd_published_at": "2026-10-21T21:17:56Z",
"github_reviewed_at": "2026-10-22T16:39:55Z"
}
},
"related_cves": [
{
"value": "CVE-2026-114142",
"evidence": "/aliases"
}
],
"security_relevant": true,
"severity_evidence": "/database_specific/severity"
},
"source_id": "core-osv",
"document_id": 454226,
"published_at": "2026-10-22T16:39:55+00:00"
}