Skip to content

← Public intelligence

npm package

re2

Open actionable advisories and recorded vendor fixes. This public package view has no inventory attached and cannot establish whether your deployment is affected. A vendor fix never resolves your finding; verify your installed version and the source guidance.

Open advisories

4 actionable advisories, newest first. Withdrawn advisories and news are excluded. Coverage is partial.

  1. Medium, CVSS 5.1npmPublished

    node-re2: Out-of-bounds heap read in replace/split via a Buffer ending in a truncated multi-byte UTF-8 character → adjacent heap memory disclosed to JavaScript

    CVE-2026-71498 · GHSA-j4r3-hg7j-8chg

    Affected
    • npm re2 <= 1.26.0
    Fixed in
    1.26.1· Vendor fix available
    Issue
    re2 infers a character's byte length from its UTF-8 lead byte alone, with no bound on the bytes actually remaining in the input. Buffer arguments reach the native layer verbatim — only strings are re-encoded into well-formed UTF-8 — so a Buffer whose last byte is a multi-byte lead promises continuation bytes that are not there, and the result builders read up to 3 bytes past the end of the buffer. In replace() and split() those bytes are copied into the returned Buffer, disclosing adjacent heap memory to JavaScript. The trigger is deterministic and requires no special heap grooming. Only Buffer input is affected. String input was never at risk: re-encoding guarantees every multi-byte sequence is complete. Root cause getUtf8CharSize maps a lead byte to a length of 1–4 and never sees the input size: Callers then read that many bytes. In the zero-width branch of replace(), the guard proves only that at least one byte remains: offset < size permits offset == size - 1, so a lead…

    Recommended action: Upgrade to 1.26.1 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  2. Medium, CVSS 6.2npmPublished

    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

    CVE-2026-71430 · GHSA-8hcv-x26h-mcgp

    Affected
    • npm re2 <= 1.25.0
    Fixed in
    1.25.1· Vendor fix available
    Issue
    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): 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::ReportApiFailure → FATAL ERROR: v8::ToLocalChecked Empty MaybeLocal → abort() (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…

    Recommended action: Upgrade to 1.25.1 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  3. Medium, CVSS 5.7npmPublished

    re2: Out-of-bounds heap read in exec/test/match via attacker-influenced lastIndex on a non-ASCII subject → uncatchable process crash (DoS)

    CVE-2026-67550 · GHSA-ff84-5f28-78qj

    Affected
    • npm re2 <= 1.25.1
    Fixed in
    1.25.2· Vendor fix available
    Issue
    re2 validates the user-settable lastIndex against the subject's UTF-8 byte length but then uses it as a UTF-16 code-unit count to walk the subject buffer, with no bounds check. For any non-ASCII subject, the byte length is larger than the true character count, so a lastIndex between those two values passes validation while pointing past the end of the buffer. The subsequent walk reads out of bounds. With a large subject the read marches into unmapped memory and the process dies with SIGABRT/SIGSEGV — an uncatchable crash (try/catch cannot stop it), i.e. a denial of service for any worker/process that runs the match. In some cases the out-of-bounds bytes are copied into the returned value (a bounded, best-effort heap information leak). Root cause The subject wrapper stores the UTF-8 byte length in StrVal::length: - lib/addon.cc:200 auto argLength = utf8Length(s, isolate); — UTF-8 byte count - lib/addon.cc:209 lastStringValue.reset(buffer, argSize, argLength, startFrom, false,…

    Recommended action: Upgrade to 1.25.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →
  4. Medium, CVSS 6.2npmPublished

    re2: Global String.prototype.match with an empty-matchable pattern never advances → infinite loop with unbounded native memory growth (DoS)

    CVE-2026-68499 · GHSA-6hxr-mr5r-9836

    Affected
    • npm re2 <= 1.25.1
    Fixed in
    1.25.2· Vendor fix available
    Issue
    String.prototype.match with a global RE2 collects all matches in a native loop that advances the cursor by the match length. A zero-width (empty) match has length 0, so the cursor never advances: the same empty match is found forever and appended to an ever-growing native vector. Any pattern that can match the empty string (a, b?, x{0,3}, (a)|, (?:), …) therefore causes an infinite loop with unbounded memory growth. The call is synchronous native code, so it blocks the entire event loop and cannot be interrupted by try/catch, AbortController, --max-old-space-size, or timers — the process must be killed externally. This diverges from the built-in engine, where 'xxxx'.match(/a/g) returns a finite array. Root cause When match.size() == 0, byteIndex is unchanged, so the next iteration matches the same empty position again; groups grows without bound. The other iteration paths already guard this: lib/split.cc:50-55 advances by getUtf8CharSize on an empty match, and exec advances…

    Recommended action: Upgrade to 1.25.2 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.comSource checked Evidence →