Overview

Low
Severity
8.8
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactType confusion in V8
DescriptionType confusion in V8
ComponentV8
Sub-componentWASM
Bug ClassType Confusion
Action tierwatch — corruption primitive but gated (uncommon) — not default-reachable
Computed by PatchGap's deterministic exploitability ruler from the fixing commit. patch-now = RCE-class & attacker-reachable in a default config, or exploited in the wild; watch = real security signal below that bar; noise = no security relevance.
Tracker520016142
Fix commitef82f91627ad (v8/v8) +10/-0
CWECWE-843 (Type confusion)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CISA KEVNot listed
CreditedGoogle
Reported2026-06-04 (per vendor advisory)
Fix landed2026-07-01 (public git)
Disclosed2026-08-25
Patch gap55 days — fix public in source before the advisory

Background

Liftoff
V8’s baseline single-pass WebAssembly compiler that emits machine code quickly, used heavily when a module is being debugged (for_debugging_).
OSR (On-Stack Replacement)
the mechanism that hot-swaps a running function’s execution into a freshly recompiled code object mid-execution; Liftoff records where to resume via an OSR target stored in kOSRTargetSlot.
Exception landing pad
the code region a Liftoff frame unwinds to when a callee throws, where the handler runs the Wasm catch body via ExceptionHandler and PushException.
`ResetOSRTarget`
a Liftoff assembler helper that clears any pending OSR target so the next instruction does not attempt to jump into a recompiled continuation.

Root Cause Analysis

When a Wasm module is debugged, setting a breakpoint in a caller while paused in a callee triggers recompilation of the caller and computes an OSR target for the call’s return continuation, stored in kOSRTargetSlot. If the callee then throws, control unwinds not to that return continuation but to the caller’s exception landing pad emitted by LiftoffCompiler, so the previously computed OSR target is stale for the path actually being taken. The vulnerable code in the landing-pad emission bound the handler, called ExceptionHandler, and proceeded to PushException without invalidating the pending OSR target, violating the invariant that an OSR target is only consumed on the normal return continuation it was computed for. As a result the next instruction could consume the stale OSR target and transfer control into a code object/continuation that does not match the current frame state, producing the type confusion.

The fix adds a guarded __ ResetOSRTarget() in the landing pad under V8_UNLIKELY(for_debugging_), clearing the slot so the catch body keeps executing in the current code object instead of jumping through a mismatched OSR continuation.

Key insight
The single mistake is treating the OSR target computed for a call’s normal return continuation as still valid after unwinding to the exception landing pad; the fix invalidates that target with ResetOSRTarget on the exceptional path so no stale continuation is ever consumed.

Attack Path

  1. Attacker-controlled Wasm under debug The attacker arranges for a WebAssembly module to run with for_debugging_ Liftoff code, which is reachable through DevTools/debugger interactions the page can influence.
  2. Force caller recompilation A breakpoint is set in a caller function while execution is paused inside a callee, causing the caller to be recompiled and an OSR target to be written into kOSRTargetSlot for the call’s return continuation.
  3. Throw from the callee The callee raises an exception so the engine unwinds to the caller’s exception landing pad instead of returning normally to the continuation the OSR target described.
  4. Consume the stale OSR target Because the landing pad never cleared kOSRTargetSlot, the next instruction consumes the stale target and transfers into a continuation mismatched with the live frame, yielding a type confusion.
  5. Leverage the confusion The attacker uses the resulting type-confused state to corrupt memory and escalate toward arbitrary read/write in the renderer.

Impact Assessment

An attacker gains a type confusion in V8 running inside the renderer process, which is a strong primitive typically leading to memory corruption and potential remote code execution within the sandbox. Exploitation requires the Wasm module to be executing in a debugging context (for_debugging_ Liftoff code) with a breakpoint set in a caller while paused in a callee, and a callee exception to force the exceptional unwind. The window is narrow but reachable via debugger-driven state, making it a serious in-process escalation primitive.

Files Changed

  • src/wasm/baseline/liftoff-compiler.cc

Audit Directions

  • Stale continuation state on exceptional paths
    Review other Liftoff and baseline exception/unwind paths to confirm any OSR target, deopt data, or return-continuation slot computed for normal returns is invalidated before the handler resumes.
  • Debug-only recompilation transitions
    Audit code guarded by for_debugging_ where breakpoint-driven recompilation mutates per-frame slots like kOSRTargetSlot, ensuring every alternate exit (throw, tail call, trap) resets or re-derives that state.
  • OSR slot lifecycle
    Trace all writers and consumers of kOSRTargetSlot and ResetOSRTarget/SetOSRTarget to verify the slot is always cleared on paths that diverge from the continuation it was computed for.
From ef82f91627adf19af488e1190eeedfcb0d8278ff Mon Sep 17 00:00:00 2001
From: Thibaud Michaud <thibaudm@chromium.org>
Date: Tue, 30 Jun 2026 17:13:21 +0200
Subject: [PATCH] [wasm][debug] Reset OSR target on exception landing pad in Liftoff

When debugging, if we set a breakpoint in a caller function while paused
in a callee, the caller function is recompiled. If the callee then
throws an exception, we unwind to the caller's exception landing pad.

Any pending OSR target computed for the call's return continuation is
stale on the exception path. Clear it to ensure we don't consume it at
the next instruction.

Fixed: 520016142
Change-Id: I923c3d7d9c05ce596e5ea6e879f8ee4722f4eb85
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/8024909
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#108357}
---
diff --git a/src/wasm/baseline/liftoff-compiler.cc b/src/wasm/baseline/liftoff-compiler.cc
index 1b9ec0a..681efb6 100644
--- a/src/wasm/baseline/liftoff-compiler.cc
+++ b/src/wasm/baseline/liftoff-compiler.cc
@@ -6139,6 +6139,16 @@
     CODE_COMMENT("-- landing pad --");
     __ bind(handler.get());
     __ ExceptionHandler();
+    if (V8_UNLIKELY(for_debugging_)) {
+      // Any pending OSR target was computed for the call's return continuation
+      // and is stale on the exception path; clear it so we keep executing the
+      // catch body in this code object.
+      // We might miss breakpoint updates by staying in the old code.
+      // TODO(thibaudm): Get the exception handler address in the new code and
+      // jump to it. Maybe by using a second OSR slot on top of kOSRTargetSlot,
+      // specifically for exceptional returns.
+      __ ResetOSRTarget();
+    }
     __ PushException();
     handlers_.push_back({std::move(handler), handler_offset});
     Control* current_try =
Loading diff…

Original Bug Report

The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.