OOBRace 3 CVEs 3 mapped CWE-362CWE-787 2025-10 → 2026-04

V8 reads a resizable or growable ArrayBuffer’s length or byte-length twice with a background-thread grow in between, desynchronizing the two snapshots. A destination array sized from the earlier value is then filled using a larger current length re-read live from the backing store. The mismatch produces an out-of-bounds write.

Invariant
An operation over a resizable/growable buffer must derive both the allocation size and the iteration bound from a single consistent length snapshot, never re-reading the live length after the destination has been sized.

Mechanism

A growable shared buffer’s mutable length was re-read after its byte length, letting a background grow desynchronize the two (CVE-2025-12432). In array collection, the destination was sized from an earlier length while the loop trusted a possibly-larger current length re-read live from a concurrently grown TypedArray, overflowing the destination (CVE-2026-4450, CVE-2026-5893).

Fix shape

Derive the element count from a single length snapshot and pass that original count down as an explicit bound, rather than re-reading the live, concurrently-growable length during collection.

CVEs in this pattern

1 component · V8
CVEWhatComponentVendorSeverityMonth
CVE-2026-5893 Race in V8 V8 chrome Medium 2026-04 🔧
CVE-2026-4450 OOB in V8 V8 chrome High 2026-03 🔧
CVE-2025-12432 Race in V8 V8 chrome High 2025-10 🔧

Hunt for siblings

Commit-scanner flags functions that read a RAB/GSAB length or byte_length more than once; a fuzzer that grows a shared buffer from a background thread mid-operation surfaces the desync overflow.

Mitigations that would catch this class

  • Snapshot the length once and reuse it for both sizing and iteration
  • Pass the sampled element count as an explicit bound into inner loops
  • Derive element count from byte_length rather than re-reading a mutable length