V8 Array Iterator Maglev Type Confusion — addrof/fakeobj Primitives (CVE-2026-14431)
by Jafork (jaf0rk) · 2026-07-19
- Severity
- High
- CVE
- CVE-2026-14431
- Category
- binary
- Affected product
- V8 JavaScript engine (Google Chrome and other Chromium-based browsers)
- Affected versions
- Google Chrome prior to 150.0.7871.46; PoC developed/tested against V8 14.9.207.29
- Disclosed
- 2026-07-19
- Patch status
- unpatched
Tags
References
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-19 |
| Last Updated | 2026-07-19 |
| Author / Researcher | Jafork (jaf0rk) |
| CVE / Advisory | CVE-2026-14431 |
| Category | binary |
| Severity | High |
| CVSS Score | 8.8 (CVSS 3.1, AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H) |
| Status | PoC — real, working sandboxed read/write primitives (addrof/fakeobj); no sandbox-escape/RCE chain published (author states this is still in progress) |
| Tags | v8, javascript-engine, chromium, maglev, type-confusion, array-iterator, cwe-843, sandboxed-read-write, memory-corruption |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | V8 JavaScript engine (Google Chrome and other Chromium-based browsers) |
| Versions Affected | Google Chrome prior to 150.0.7871.46; PoC developed/tested against V8 14.9.207.29 |
| Language / Platform | C++ (V8’s Maglev mid-tier JIT compiler), triggered via JavaScript |
| Authentication Required | No |
| Network Access Required | Yes — victim must load a crafted HTML/JS page (user interaction required, UI:R) |
Summary
Array.prototype[Symbol.iterator]().next() is miscompiled by V8’s Maglev JIT tier: ArrayIteratorPrototypeNext fails to re-check the map (elements kind) of an inlined array after a side effect can change it mid-call, leading to a type confusion between PACKED_DOUBLE_ELEMENTS and tagged/pointer elements. By forcing a map transition on the iterated array from inside a re-entrant callback (triggered via Function.prototype.arguments access on a still-executing frame) while Maglev-compiled code still believes the array’s old elements kind is in effect, an attacker gets the JIT to treat a raw double value as a tagged pointer (or vice versa). This yields classic addrof/fakeobj primitives — reading a JS object’s address and forging fake objects at attacker-chosen addresses — giving read/write access within V8’s memory sandbox. The bug was fixed upstream by adding a map check for the inlined array in ArrayIteratorPrototypeNext (Chromium bug 523884658).
Vulnerability Details
Root Cause
Tracked upstream as a V8 Maglev type confusion (CWE-843, Type Confusion). Maglev inlines ArrayIteratorPrototypeNext and, for a PACKED_DOUBLE_ELEMENTS or plain tagged array, assumes the array’s elements-kind map stays constant for the duration of the inlined function. The PoC defeats this by triggering a re-entrant call during iteration: a wrapper function reads .arguments off a still-live outer frame (eval('tagged_inner.arguments') / eval('double_inner.arguments')) and uses it to overwrite the array’s backing elements with a different representation (tagged object vs. double) between the map check and the actual element read that Maglev compiled assuming the old map. The JIT then reads the new representation’s bits as if they were still the old type — a double value gets reinterpreted as a tagged pointer, or vice versa, without any bounds/type validation in between.
Attack Vector
- Warm up two pairs of functions (
tagged_outer/tagged_inner/tagged_next/tagged_reflectand thedouble_*equivalents) in a tight loop (0x8000iterations) so Maglev JIT-compilesArrayIteratorPrototypeNextfor both a tagged-value array and a double-value array. - Flip a
transitionflag so that, on the next call, the re-entrant*_reflect()function (invoked via.argumentsaccess on the currently-executing inlined frame) overwrites the iterated array’s elements with an attacker-controlled tagged value or double, exploiting the same map-staleness window Maglev’s inlining relies on. - The type-confused read/write is used to build
addrof(obj)(leak an object’s address by confusing it into a raw double) andget_fake_obj(addr)/cage_read/cage_write(forge a fakePACKED_DOUBLE_ELEMENTSarray object at an attacker-chosen address, using a stable, build-specific compressed map pointer, to get arbitrary read/write within the V8 sandbox). - From there, an attacker can corrupt further JS engine internals to build toward full code execution — though this specific PoC stops at the sandboxed read/write primitive stage.
Impact
Per Google’s own advisory: “Type Confusion in V8 in Google Chrome… allowed a remote attacker to execute arbitrary code inside a sandbox via a crafted HTML page” (Chromium security severity: High). This PoC provides the memory read/write primitives that such an exploit chain would be built on; the author explicitly notes no V8-sandbox-escape has yet been identified to chain with it, so as published this achieves sandboxed corruption/read-write, not a full browser-to-OS compromise.
Environment / Lab Setup
OS: Ubuntu 24.04 noble x64
V8 version: 14.9.207.29 (commit 6511f6cfab1f24c360d0fb737d205c27da48a623)
Build args: is_debug = false
dcheck_always_on = false
v8_symbol_level = 2
v8_enable_object_print = true
v8_enable_sandbox = true
target_os = "linux"
target_cpu = "x64"
Setup Steps
Build a matching V8/d8 shell from the commit above with the listed gn args (or use a Chrome build prior to 150.0.7871.46 with --allow-natives-syntax-equivalent debug hooks).
Proof of Concept
See
exp.jsin this folder — mirrored from jaf0rk/CVE-2026-14431. Verified before ingestion: read the full script — a compact, technically coherent V8 exploit using standard, well-documentedaddrof/fakeobjconstruction techniques (float/bigint reinterpretation via a sharedArrayBuffer, GC-triggering helpers, iterator re-entrancy via.arguments). No obfuscation, no unrelated network or filesystem access — everything operates purely on in-process V8 JS objects. Cross-checked the linked bug fix (chromium-review.googlesource.com/c/v8/v8/+/7950517, Chromium issue 523884658, “[maglev] Check map of inlined array in ArrayIteratorPrototypeNext”) against NVD’s own description of CVE-2026-14431 (“Type Confusion in V8… via a crafted HTML page”) — consistent and specific, not a generic/templated writeup. The author’s own caveat that no sandbox-escape chain exists yet is a realistic, non-oversold claim rather than a “full RCE” overstatement.
Step-by-Step Reproduction
| |
Exploit Code
| |
Expected Output
Running under d8 --allow-natives-syntax exp.js prints the debug representation of a forged fake object aliased over an attacker-chosen address (via %DebugPrint) and drops into %SystemBreak() for interactive inspection — confirming addrof/fakeobj succeeded and arbitrary sandboxed read/write via cage_read/cage_write is live.
Detection & Indicators of Compromise
Remediation
| Action | Detail |
|---|---|
| Patch | Upgrade Google Chrome (or any Chromium-based browser) to 150.0.7871.46 or later, which includes the map-check fix in ArrayIteratorPrototypeNext. |
| Workaround | None beyond staying current on browser updates — this is a JIT-compiler correctness bug in the shipped engine, not a configuration issue. |
References
- Chromium fix commit — “[maglev] Check map of inlined array in ArrayIteratorPrototypeNext”
- Chromium bug 523884658
- NVD — CVE-2026-14431
- Public PoC — jaf0rk/CVE-2026-14431
Notes
Flagged directly by the user for ingestion, then verified before archiving per this archive’s standing rule: read exp.js in full and cross-checked the referenced Chromium fix commit and bug ID against NVD’s own CVE-2026-14431 description — consistent and specific. The author candidly notes this PoC provides sandboxed read/write primitives only; no V8-sandbox-escape chain has been published to extend this to full renderer-to-OS code execution.
| |