Sep 3, 2026·6 min read·35 visits
A stack exhaustion vulnerability in toml-node allows remote attackers to crash Node.js application servers by submitting deeply nested arrays or inline tables, triggering a process-terminating RangeError.
An uncontrolled recursion vulnerability (CWE-674) in the toml-node NPM package (published as toml) prior to version 4.2.0 allows unauthenticated remote attackers to trigger process-wide Denial of Service (DoS) crashes. By submitting TOML payloads with deep bracket or brace nesting, attackers exhaust the V8 runtime stack limit.
The toml-node library (published as toml on the NPM registry) is an engine used to parse TOML (Tom's Obvious Minimal Language) configuration files and payloads in Node.js applications. In microservices and web applications, configurations or incoming API requests may be represented in TOML formats. This library acts as the primary deserialization mechanism for such datasets.
Prior to version 4.2.0, the core parser implemented in toml-node is susceptible to uncontrolled recursion when processing deeply nested arrays or inline tables. An attacker who is able to submit crafted inputs to an application using this library can consume all available stack frames, triggering an unhandled exception. This exhaustion happens because the parsing logic performs a sequence of function calls that maps directly to input nesting depth.
Because Node.js operates on a single-threaded event loop by default, an uncaught runtime error of this nature does not merely fail the individual transaction. Instead, it crashes the entire node process. This behavior elevates the impact of a simple parsing exception to an application-wide Denial of Service (DoS) state.
The root cause of CVE-2026-77465 lies in the mutual recursion defined in the parser's PEGjs grammar file (src/toml.pegjs). toml-node utilizes Peggy (specifically version 5.1.0) to generate its parser code. Peggy compiles Parsing Expression Grammars into recursive-descent parsers, where each grammar rule compiles into a JavaScript function.
In the vulnerable grammar structure, the rules governing values, arrays, and inline tables reference each other recursively. Specifically, the value rule can match an array or an inline_table. An array contains nested elements that must be evaluated against the value rule, and an inline_table contains key-value pairs where each value is again parsed using the value rule.
When processing nesting, the generated parser executes a series of nested function calls. This process repeats for every level of nesting in the input string. This pattern forms a direct recursion path: peg$parsevalue to peg$parsearray to peg$parsevalue.
The V8 engine utilized by Node.js maintains a platform-dependent call stack size limit, typically ranging from 10,000 to 104,000 frames. Because there are no limits on the depth of the recursive calls inside the toml-node grammar, a highly nested payload easily exhausts this allocation. This results in a synchronous, uncatchable RangeError exception.
In vulnerable versions of toml-node, the src/toml.pegjs grammar file does not track depth. The rules evaluate child elements recursively without checking how deep the execution flow has descended. The patch introduced in commit 967b8b06754f3ecd9863cea118dc50792a8c353f mitigates this vulnerability by tracking state and establishing a maximum depth limit.
Below is a simplified differential analysis of the grammar modifications implemented to fix this vulnerability:
// --- PATCH ADDITIONS IN INITIALIZATION BLOCK ---
// A maximum depth option is introduced, defaulting to 500
var depth = 0;
var MAX_DEPTH = (options && options.maxDepth != null) ? options.maxDepth : 500;// --- GRAMMAR RULE PATCH ---
// Vulnerable Grammar:
// value = string / number_or_date / boolean / array / inline_table
// Patched Grammar:
// The value rule now uses a semantic predicate to check depth
value
= &{ if (++depth > MAX_DEPTH) { depth--; genError("Maximum nesting depth of " + MAX_DEPTH + " exceeded.", offset()); } return true; }
v:value_choice { return v; }
value_choice
= v:value_body { depth--; return v; }
/ &{ depth--; return false; }
value_body
= string / number_or_date / boolean / array / inline_tableThe implementation uses a semantic predicate &{ ... } to increment depth. If the limit is reached, it decrements the counter to maintain alignment and generates a parse error. The value_choice rule ensures that whether parsing succeeds (via value_body) or fails (triggering backtracking), the depth counter is correctly decremented.
Exploitation of CVE-2026-77465 requires no privileges and can be executed via any interface that accepts TOML payloads and feeds them directly into toml.parse(). Since many microservices accept user-defined config data, settings, or request payloads in TOML format, the attack vector remains highly accessible.
To trigger the crash, an attacker prepares a payload containing thousands of nested brackets or braces. The payload is designed to force the recursive descent parser into thousands of self-referencing loops, quickly exceeding the call stack limit of the target host.
An attacker can construct a payload consisting of a variable containing 10,000 nested arrays:
a = [[[[[[...[1]...]
Alternatively, the attacker can use a payload consisting of nested inline tables:
a = {b={b={b={...{b=1}...}}}}
The execution of toml.parse() on this payload will immediately trigger the uncaught RangeError, resulting in the failure of the application thread. Because Node.js single-threaded applications usually lack automatic recovery wrappers around parse libraries, the entire process terminates, disrupting services for all active users.
The technical impact of CVE-2026-77465 is classified as a High-severity Denial of Service (DoS) vulnerability, holding a CVSS score of 7.5. Because the vulnerability is exploited over the network (AV:N) with low complexity (AC:L) and requires no special privileges (PR:N) or victim interaction (UI:N), it poses a significant threat to internet-exposed Node.js systems processing untrusted TOML data.
Although this vulnerability does not allow for Remote Code Execution (RCE) or information disclosure (C:N/I:N), the ease with which an attacker can disrupt services makes it an attractive target. A single HTTP request with a small payload (less than 50 KB) containing the nested structures is sufficient to take down a backend worker.
In cloud environments where auto-scaling or container orchestrators (such as Kubernetes) are configured, a continuous stream of such payloads can cause a crash-loop backoff state. This exhausts container resources, incurs high cloud-billing costs, and prevents legitimate users from accessing the system.
The fix implemented in toml-node version 4.2.0 is highly robust because of how it handles the parsing state during backtracking. In PEG engines, the parser frequently backtracks when a matched path fails to satisfy a rule, reverting to try a different configuration.
If a naive depth counter had been used (e.g., simply incrementing at the start of a rule and decrementing at the end of a successful match), a backtracking action would have skipped the decrement. This would lead to a "depth leak", where the counter remains elevated despite the parser descending back to a shallow depth, eventually resulting in false-positive blocks on valid, shallow TOML elements.
By structuring the logic with value_choice and implementing a backtrack-reverting alternative predicate (/ &{ depth--; return false; }), the developer ensured that the state tracking is transactionally aligned. Security researchers have evaluated this patch and confirmed that the depth tracking handles backtracking safely, making the fix highly resilient.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
toml-node BinaryMuse | < 4.2.0 | 4.2.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-674 |
| Attack Vector | Network |
| CVSS Score | 7.5 (High) |
| EPSS Score | Not currently assigned |
| Impact | Denial of Service (DoS) |
| Exploit Status | Proof-of-concept |
| KEV Status | Not listed |
The product code contains a recursive function but lacks a structural check to ensure the call stack does not overflow.
A heap-based buffer overflow vulnerability in Pillow PyPI binary wheels (versions 11.1.0 to 12.x) allows remote code execution or application crash via crafted JPEG 2000 files processed by the bundled libopenjp2 library.
CVE-2026-109618 (dubbed PHP2Shell) is a critical vulnerability in the PHP engine core resulting from improper out-of-memory exception handling via longjmp(). When request allocation fails mid-processing, non-local control flow bypasses cleanup procedures, leaving memory structures uninitialized or in a use-after-free state during request shutdown.
CVE-2026-109619 (PHP2Shell) is a critical Use-After-Free vulnerability in the core PHP engine caused by improper global state cleanup during out-of-memory exception handling across persistent worker requests.
In Python virtualenv prior to version 21.14.9, activation script generators and configuration writers use Path.exists() before writing files. Because Path.exists() resolves symbolic links, it returns False for dangling symlinks. Consequently, virtualenv skips unlinking pre-planted symbolic links or hard links, writing data directly to target locations outside the intended virtual environment directory.
A remote code execution vulnerability exists in Microsoft .NET due to untrusted data deserialization within the PresentationCore component. The flaw stems from implicit auto-conversion flags during clipboard data retrieval operations.
An out-of-bounds write vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio allows unauthenticated remote attackers to execute arbitrary code via crafted pixel-shader bytecode or auto-converted clipboard payloads.