Aug 7, 2026·6 min read·16 visits
Vulnerable versions of node-re2 invoke .ToLocalChecked() on empty V8 handles when string allocations fail due to length limits, crashing the entire Node.js runtime process with SIGABRT.
A denial-of-service vulnerability in node-re2 prior to version 1.25.1 allows attackers to trigger uncatchable native assertion failures in the Google V8 engine. By supplying output-amplifying replacement templates, an attacker can exceed V8 string limits, resulting in an immediate process crash.
The Node.js native regular expression binding library, node-re2, wraps the Google RE2 regular expression engine to provide safe, linear-time regular expression matching. This wrapper relies on native C++ abstractions to bridge the boundary between the V8 JavaScript engine and the RE2 C++ library. The vulnerability designated as CVE-2026-71430 resides within the replacement functionality of this native addon, specifically when handling output-amplifying replacements.
The flaw is located in the WrappedRE2::Replace implementation within lib/replace.cc. It affects both String.prototype.replace(re2, template) and RE2.prototype.replace() calls. When processing regular expression replacements, the addon allocates memory buffers and V8 string structures to hold the modified output string. This process exposes an attack surface where input and replacement parameters directly influence native memory allocations.
Under normal execution, node-re2 provides immunity to Regular Expression Denial of Service (ReDoS) because of RE2's internal DFA/NFA execution limits. However, the wrapper code itself introduces a secondary denial-of-service vector. By failing to validate the status of V8 memory allocations, the wrapper permits an uncatchable native assertion failure, terminating the entire Node.js runtime process.
The root cause of CVE-2026-71430 lies in the unsafe unwrapping of v8::MaybeLocal handles returned by the Native Abstractions for Node.js (NAN) API during allocation failures. In C++ Node.js addons, operations that instantiate JavaScript types return a v8::MaybeLocal<T> wrapper, which signals potential allocation failure by returning an empty handle. This occurs when an allocation request exceeds the engine-level restrictions, such as v8::String::kMaxLength or system memory limits.
In vulnerable versions of node-re2, the developer immediately invoked .ToLocalChecked() on the MaybeLocal instances without verifying whether the handles were empty. The .ToLocalChecked() function is designed under a fail-fast paradigm. If the underlying V8 handle is empty, .ToLocalChecked() calls v8::Utils::ReportApiFailure, which executes an uncatchable native assertion crash via abort().
Because the failure is raised within the V8 engine API itself, standard JavaScript exception handlers cannot intercept or mitigate the crash. The operating system receives a SIGABRT signal, terminating the active thread and parent Node.js process immediately with exit code 134. This makes the bug class a reachable assertion (CWE-617) rather than a standard catchable JavaScript error.
The vulnerable implementation of WrappedRE2::Replace in lib/replace.cc failed to handle allocation failures when processing replacement buffers and strings. The primary issue was the immediate execution of .ToLocalChecked() on the results of Nan::CopyBuffer and Nan::New.
// Vulnerable implementation
argv.push_back(Nan::CopyBuffer(data, item.size()).ToLocalChecked());
// ...
argv.push_back(Nan::New(data, item.size()).ToLocalChecked());
// ...
if (replacee.isBuffer)
{
info.GetReturnValue().Set(Nan::CopyBuffer(result.data(), result.size()).ToLocalChecked());
return;
}
info.GetReturnValue().Set(Nan::New(result).ToLocalChecked());The patch implemented in version 1.25.1 refactored these calls to capture the returned v8::MaybeLocal handle first. The code now tests the handle using .IsEmpty(). If the allocation fails, the addon invokes Nan::ThrowRangeError to queue a standard JavaScript RangeError and returns early.
// Patched implementation in version 1.25.1
auto buffer = Nan::CopyBuffer(data, item.size());
if (buffer.IsEmpty())
{
Nan::ThrowRangeError("Invalid string length");
return Nan::Nothing<std::string>();
}
argv.push_back(buffer.ToLocalChecked());
auto text = Nan::New(data, item.size());
if (text.IsEmpty())
{
Nan::ThrowRangeError("Invalid string length");
return Nan::Nothing<std::string>();
}
argv.push_back(text.ToLocalChecked());This structural modification changes the outcome of an allocation failure from a process-terminating C++ assertion to a standard JavaScript exception. Since the range error is registered within the V8 context before returning, the JavaScript runtime can intercept the error via standard try-catch structures. This effectively addresses the vulnerability by preserving process availability.
To exploit CVE-2026-71430, an attacker must supply inputs to a regular expression replace operation that generate an output string exceeding the maximum string length permitted by V8. This maximum length, defined by v8::String::kMaxLength, is typically 512 MB on 32-bit platforms and 1 GB on 64-bit systems.
This length restriction can be exceeded using output-amplifying replacement templates, specifically the trailing-context selector $' and the leading-context selector `$``. These templates instruct the engine to replace each match with the remainder or precursor of the source string, respectively. If a target regular expression matches multiple characters globally throughout a long string, the output size grows quadratically relative to the input length.
For example, given an input string of 50,000 characters consisting of the character 'a', applying a global replace of 'a' with $' yields a cumulative series of substring copies. The length of the output is calculated as the sum of integers from 1 to 50,000, which is approximately 1.25 billion characters. When the addon attempts to construct the final JavaScript string containing this 1.25 GB result, V8 returns an empty handle, triggering the assertion failure and terminating the process.
The primary consequence of exploiting CVE-2026-71430 is a complete denial of service (DoS) of the Node.js runtime process. Because the crash occurs via a native SIGABRT signal, standard high-level application frameworks (such as Express, NestJS, or Koa) cannot recover from the crash, causing all active connections to drop and taking the service offline.
The CVSS v3.1 score is calculated as 6.2 (Medium) with the vector CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H. The attack vector is classified as Local (AV:L) because it relies on passing arguments directly into local library APIs. However, if an application exposes regex replacement parameters or processes user-supplied template strings via node-re2 over a network interface, the practical severity escalates to a remote denial of service.
The vulnerability is categorized under CWE-617: Reachable Assertion. While the flaw does not allow remote code execution or confidential data exposure, its impact on service availability is absolute. In single-process deployments without automated orchestrators (like Kubernetes or PM2), a single request can permanently disable the application until manual intervention occurs.
The primary mitigation for CVE-2026-71430 is upgrading the re2 npm package to version 1.25.1 or later. This version introduces the necessary validation of v8::MaybeLocal allocations, converting native crashes into catchable JavaScript RangeError exceptions.
For legacy systems where immediate package updates are not feasible, applications should implement input sanitization to restrict the length of both input strings and replacement templates. Specifically, applications must reject or sanitize any user-controlled replacement templates containing the amplification characters $ followed by ' or `. Restricting maximum input lengths to values well below the V8 allocation limits (e.g., limiting inputs to less than 1 MB) prevents the quadratic expansion from reaching the threshold required to trigger the allocation failure.
Additionally, production deployments should employ robust process monitoring and orchestration tools. Systems like Kubernetes, PM2, or systemd should be configured to automatically restart crashed Node.js worker instances. While process restarts do not fix the root vulnerability, they minimize the duration of the denial of service.
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
re2 uhop | < 1.25.1 | 1.25.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-617: Reachable Assertion |
| Attack Vector | Local (escalatible to Network/Remote under specific application configurations) |
| CVSS Score | 6.2 (Medium) |
| Exploit Status | Proof of Concept (PoC) verified |
| Impact | Denial of Service (DoS) via native process abort |
The program contains an assert() or similar statement that can be triggered by an attacker, leading to process termination.
A missing authorization vulnerability in Langflow versions 1.0.0 through 1.10.0 allows authenticated users (and unauthenticated users in versions prior to 1.7.2) to access private workflow structures and execute graph components by targeting deprecated API endpoints.
A critical OS command injection vulnerability exists in Langflow's Model Context Protocol (MCP) server integration using stdio transport, allowing unauthenticated remote command execution under default configurations.
Docling prior to version 2.131.0 is vulnerable to arbitrary local code execution during module initialization due to incorrect order of operations in its plugin discovery system. Even when the default option to reject external plugins is active, Docling utilizes Pluggy to scan and import entrypoints before performing namespace validation.
An uncontrolled resource consumption vulnerability exists in the Docling document conversion library. Maliciously structured HTML, JATS, ODS, or BoxNote inputs containing table cells with excessively large 'rowspan' or 'colspan' attribute values trigger algorithmic complexity conditions. This allows unauthenticated remote attackers to initiate resource exhaustion states, crashing or hanging the target document processing pipeline while bypassing configured timeouts.
A Local File Inclusion (LFI) and Arbitrary File Disclosure vulnerability exists in Docling and Docling Slim versions >= 2.16.0 up to 2.131.0. When parsing serialized DoclingDocument structures using the JSON input format, the backend fails to restrict image URI schemes, allowing remote attackers to retrieve local files and verify path existence on the host system during embedded document export.
Docling, a tool for parsing and processing diverse document formats, is vulnerable to arbitrary file read, arbitrary file write, and potential remote code execution (RCE) in versions 2.94.0 through 2.131.0. The vulnerability occurs when applications configure Docling to use the Tectonic engine for rendering TikZ diagrams into images. Because the compilation did not restrict hazardous TeX primitives or sandbox the environment, an attacker can supply crafted documents containing malicious TikZ definitions to access or modify local files and execute arbitrary commands under the privileges of the processing application.