deps(frontend): update dependency toml to v4 [security] - #8457
Merged
Conversation
flagsmith-engineering
Bot
requested review from
kyle-ssg
and removed request for
a team
September 4, 2026 03:21
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
✅ oss · depot-ubuntu-latest-arm-16 — run #20148 (attempt 1)Playwright Test Results (oss - depot-ubuntu-latest-arm-16)Details
🗂️ Previous results✅ oss · depot-ubuntu-latest-16 — run #20148 (attempt 1)Playwright Test Results (oss - depot-ubuntu-latest-16)Details
|
Contributor
Author
Edited/Blocked NotificationRenovate will not automatically rebase this PR, because it does not recognize the last commit author and assumes somebody else may have edited the PR. You can manually request rebase by checking the rebase/retry box above. |
matthewelwell
approved these changes
Sep 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
^3.0.0→^4.0.0toml-node: Prototype Pollution Leads to
Object.prototypeCorruption via__proto__Key-Path DesynchronizationCVE-2026-63376 / GHSA-v5mp-jgw5-2x6j
More information
Details
Summary
toml.parse()writes attacker-controlled keys ontoObject.prototype. The compiler protects the tables it builds by creating them withObject.create(null), which neutralizes a direct[__proto__]table. An attacker bypasses that protection by routing a table path through a scalar value and into the real prototype chain: a path such asa.b.y.__proto__.__proto__, wherea.b.yholds a number, resolves toObject.prototypeand every subsequent key/value writes onto it.The bypass succeeds because the compiler's duplicate-key guards track paths with keys that do not match the keys used during traversal. The tracking strings and the traversal strings desynchronize, so the guard that should reject descending through an existing scalar never fires.
Steps to reproduce
Install the latest version and run the comma-desynchronization payload.
Observe that a freshly created object inherits the injected key, confirming
Object.prototypewas modified:Confirm the prefix-clear variant reaches the same result:
A nested gadget object is also injectable, not only scalar keys:
Technical details
The compiler builds the result tree in
lib/compiler.js. Tables are created with a null prototype, so a direct[__proto__]table only sets an ordinary own property and does not pollute:The defect is in
deepRef, which resolves a table path by walking each key segment of the live object graph:Two problems combine:
1.
deepReftreats__proto__(andconstructor,prototype) as ordinary traversable keys. Line 200 executesctx = ctx[key]for every segment with no reserved-key check. When traversal reaches a scalar value — for example the number1stored ata.b.y— the next two__proto__segments evaluate toNumber.prototypeand thenObject.prototype. The null-prototype hardening covers only the container tables the compiler creates; it does not cover the values stored in them, and those values carry normal prototypes.2. The guard on line 197 is defeated by a path-format desynchronization.
currentPathis assigned two incompatible types:setPathstores an array (currentPath = path, line 151) whileaddTableArraystores a string (currentPath = quotedPath, line 172). Whenassignlater builds the path of a value, it concatenates that array with a string:For the table
[a.b],currentPathis the array["a","b"], socurrentPath + "."coerces it viaArray.toString()to the comma-joined string"a,b". The valuey = 1is therefore recorded as"a,b.y". ButdeepRef, walking the patha.b.y.__proto__.__proto__, buildstraversedPathwith dots and checksvalueAssignments.has("a.b.y"). The set contains"a,b.y", not"a.b.y", so the lookup misses and the guard never raises "Cannot redefine existing key". Traversal proceeds through the scalar1intoObject.prototype.Instrumenting the tracking sets after parsing the payload confirms the mismatch:
A second route reaches the same state without the comma trick. A table array
[[a]]triggers the prefix-clearing loop inaddTableArray, which deletes tracking entries by string prefix and wipes the guard state before the__proto__descent:Impact
toml.parse()on a TOML document an attacker can influence — uploaded configuration, project manifests, multi-tenant settings, package metadata — allows the attacker to write arbitrary properties ontoObject.prototype.tomlreports roughly 14.8 million weekly downloads and around 1,340 dependents, so the transitive exposure is large. Dependents that passtomlas the engine to front-matter or configuration loaders inherit the issue.Credit: Duy Bui / @calif.io
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:LReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
toml-node: Uncontrolled Recursion
CVE-2026-77465 / GHSA-82x6-q7mm-w9cf
More information
Details
Summary
toml.parse()crashes with an uncaughtRangeError: Maximum call stack size exceededwhen parsing deeply nested arrays or inline tables. The parser is generated by Peggy 5.1.0 (a PEG parser generator) as a recursive-descent parser; the value rule mutually recurses with the array and inline-table rules with no depth limit, so nesting depth equal to the input depth exhausts Node's call stack.A small payload — a bare array nested a few thousand levels deep (~5–6 KB) — reliably crashes the process on a default Node.js configuration.
tomlhas ~47 million monthly downloads.Vulnerable Code
The parser is a generated recursive-descent parser (
lib/parser.js, header:// @​generated by Peggy 5.1.0.). The recursion sink is the mutual recursion between thevalue,array, andinline_tablerule functions — none carry a depth counter:Recursion cycle for
a=[[[ … ]]](bare nested arrays):Inline tables (
{arr=[ … ]},{a={a= … }}) reach the same cycle viapeg$parseinline_table/peg$parseinline_table_entry. Because the parser is machine-generated, there is no hand-written function to patch; the fix belongs in the grammar (src/toml.pegjs) or in an input guard (see Suggested Fix).Confirmed PoC (toml 4.1.2, Node.js v24.16.0)
Setup:
Reproduce — save as
poc.js, runnode poc.js:Expected output (vulnerable — actual run):
Verified crash thresholds (fresh process, single parse, default Node 24 stack):
a=[[ … ]]{arr=[ … ]}Realistic Attack Scenario
An unauthenticated attacker POSTs a ~6 KB deeply nested body (well under the 100 KB limit).
toml.parseoverflows the stack and throwsRangeError; any handler that only special-cases syntax errors rethrows it, taking down the request (and, depending on the server, the worker).Impact
Any Node.js application that calls
toml.parse()on untrusted input is exposed to a remote, unauthenticated denial of service via a small (~5–6 KB) deeply nested payload.toml.parseis the package's only public API, and TOML is commonly parsed from user-supplied config/upload endpoints. With ~47 million monthly downloads and 0 existing CVEs, the exposure is broad.RangeErroris a subclass ofError(not of the parser'sSyntaxError), so it bypasses the usual "is this a parse error?" checks and propagates as an unexpected exception.Suggested Fix
Because
lib/parser.jsis generated, the fix should be applied at the grammar level and regenerated, or guarded at the entry point:Option 1 — grammar-level depth guard (
src/toml.pegjs), then re-run Peggy:Option 2 — entry-point guard in
index.js(reject pathological input before parsing):Immediate mitigation (users, verified): bound untrusted input length and bracket-nesting depth before calling
toml.parse(), e.g. reject payloads whose maximum[/{nesting exceeds a few hundred. A byte-length limit alone is insufficient (5 KB already crashes).Comparison with Related Vulnerabilities
Same CWE-674 class as the recursion-DoS findings in the PyPI
tomlpackage (C055) and the YAML parsers (PyYAML GHSA-r9mm-j37c-pjwp, ruamel.yaml). The distinguishing detail here: the parser is generated by Peggy, so the recursion lives inpeg$parsevalue/peg$parsearray/peg$parseinline_tableand cannot be fixed by editing a hand-written function — the earlier draft of this report incorrectly showed hand-writtenparseValue(tokens, index)functions that do not exist in the package.Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:HReferences
This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).
Release Notes
BinaryMuse/toml-node (toml)
v4.2.0Compare Source
=====================
GHSA-82x6-q7mm-w9cf(CVE pending), in which deeply nested arrays or inline tables could overflow the call stack and crash the process with an uncatchableRangeError. Nesting is now bounded (default 500 levels), and input past the limit throws a normal parse error. The limit is configurable viatoml.parse(input, { maxDepth }).v4.1.2Compare Source
=====================
Object.prototypeprocess-wide.v4.1.1Compare Source
=====================
v4.1.0Compare Source
=====================
v4.0.1Compare Source
=====================
v4.0.0Compare Source
=====================
Configuration
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR has been generated by Mend Renovate.