🛡️ CVE-2026-71430 — re2

🟡 CVSS 6.2 — Medium ✅ No Known Exploit CWE-617 NVD
6.2
CVSS Score
0 Low4 Medium7 High9 Critical10

Description

node-re2: String.prototype.replace(re2, template) aborts the Node process (uncatchable ToLocalChecked on empty MaybeLocal) when the result exceeds V8's max string length

Description

WrappedRE2::Replace builds the replacement result and hands it to V8 with .ToLocalChecked() without checking for the empty MaybeLocal that V8 returns when the string/buffer exceeds its maximum length:

lib/replace.cc (v1.24.1):

```cpp

// L553 — Buffer return path

info.GetReturnValue().Set(Nan::CopyBuffer(result.data(), result.size()).ToLocalChecked());

// L556 — String return path

info.GetReturnValue().Set(Nan::New(result).ToLocalChecked());

```

When a global replace uses an output-amplifying template — $' (text after the match) or ` $ ` (text before the match) — the result grows to O(input²). For an input of ~40,000+ identical single-char matches the result exceeds V8's String::kMaxLength (~536,870,888 chars on 64-bit). Nan::New(result) then returns an empty MaybeLocal, and the unchecked .ToLocalChecked() calls v8::Utils::ReportApiFailureFATAL ERROR: v8::ToLocalChecked Empty MaybeLocalabort()` (SIGABRT).

This is an uncatchable crash: it is not a JavaScript exception, so a surrounding try/catch cannot stop it — the entire Node process (or worker) dies.

The built-in regex engine handles the identical case correctly by throwing a *catchable* RangeError: Invalid string length. node-re2 diverges from that contract and aborts instead.

Proof of concept

```

npm i re2

node poc.js

```

```js

const RE2 = require('re2');

// Built-in engine: same case -> CATCHABLE RangeError (correct)

try { 'a'.repeat(50000).replace(/a/g, "$'"); }

catch (e) { console.log('native:', e.constructor.name, e.message); } // RangeError: Invalid string length

// re2: ABORTS the whole process (uncatchable; try/catch does not help)

'a'.repeat(50000).replace(new RE2('a', 'g'), "$'");

// -> FATAL ERROR: v8::ToLocalChecked Empty MaybeLocal (process exits 134 / SIGABRT)

```

Observed (Node v24, clean npm i re2[email protected]): native branch prints RangeError: Invalid string length; the re2 branch aborts with FATAL ERROR: v8::ToLocalChecked Empty MaybeLocal, stack top WrappedRE2::Replace, process exit code 134.

Threshold matches the mechanism precisely: input of 30,000 chars completes; 40,000 aborts (30000²/2 ≈ 4.5e8 < 5.37e8 max; 40000²/2 ≈ 8e8 > max). $&/constant templates and non-global replaces do not amplify and do not crash.

Impact

A remote, unauthenticated denial of service against any service that runs String.prototype.replace / the re2 [Symbol.replace] path where either the replacement template (containing $' or ` $ `) or the input size is attacker-influenced. Because the failure is a native abort(), it cannot be contained by try/catch` or domains — one request takes down the whole process/worker. This is especially impactful for re2's core audience, who adopt it specifically to process untrusted patterns/inputs safely.

Suggested fix

Check the MaybeLocal before ToLocalChecked on both return paths (and the intermediate group-string builds), and throw a catchable RangeError to match the built-in engine:

```cpp

auto maybe = Nan::New(result);

if (maybe.IsEmpty()) { Nan::ThrowRangeError("Invalid string length"); return; }

info.GetReturnValue().Set(maybe.ToLocalChecked());

```

(Apply equivalently to the Nan::CopyBuffer(...) buffer path at L553 and to the per-group Nan::New(data, size).ToLocalChecked() sites used by the replacer-function path.)

Resolution

Resolved in re2 1.25.1. WrappedRE2::Replace now checks the returned MaybeLocal on every result path and throws a catchable RangeError: Invalid string length (matching the built-in engine) instead of aborting the process with an uncatchable SIGABRT. No API changes --- upgrade to re2 >= 1.25.1 via a plain npm upgrade to receive the fix.

How this vulnerability can be exploited

This issue can be reached with local access to the system, attack complexity is low, an attacker needs no privileges on the target. No user interaction is required. The scope is unchanged, so the impact stays within the vulnerable component. Rated impact: confidentiality none, integrity none, availability high.

Affected software

CVE-2026-71430 is recorded against 2 packages.

  • re2
  • unknown

Timeline and source

Published on 6 August 2026. No public exploit is currently recorded for this entry. Record sourced from NVD.

References

github.com (Web)
github.com (Package)

Details

Severity Medium
CVSS Score 6.2
CVSS Vector CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
CWE CWE-617
Public Exploit ✅ No
Source NVD
Published 2026-08-06
Updated 2026-08-12
Modified 2026-08-06
Fix URL N/A

Affected Packages

Software From version Fixed in
re2
unknown

Similar Threats

Vulnerability Monitoring

Track new vulnerabilities in re2

CVE-2026-71430 is rated CVSS 6.2 Medium. BotEraser monitors your WordPress installation and notifies you when software you use appears in our vulnerability database.

Set Up Free Alerts →

No credit card required  ·  Results in minutes

ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.