Share
## https://sploitus.com/exploit?id=75D8AF60-1BE7-5841-A5AC-CC59A30D14EB
# CVE-2026-13036 β€” Use-After-Free in Blink (`WidgetBase::UpdateSurfaceAndScreenInfo`)

![CVE](https://img.shields.io/badge/CVE-2026--13036-red)
![Severity](https://img.shields.io/badge/Severity-High-orange)
![CVSS](https://img.shields.io/badge/CVSS-8.8-orange)
![CWE](https://img.shields.io/badge/CWE--416-Use--After--Free-yellow)
![Component](https://img.shields.io/badge/Component-Blink%20Widget-blue)

> A use-after-free vulnerability in Google Chrome's Blink rendering engine that
> allows a remote attacker to execute arbitrary code inside the renderer sandbox
> via a crafted HTML page. The flaw lives in the widget compositing layer
> (`WidgetBase`) and is reached through a re-entrant screen-orientation callback.

| | |
|---|---|
| **CVE** | CVE-2026-13036 |
| **CWE** | CWE-416 (Use After Free) |
| **CVSS 3.1** | 8.8 (High) β€” `AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H` |
| **Component** | Blink β€” `third_party/blink/renderer/platform/widget/widget_base.cc` |
| **Fixed in** | Chrome **149.0.7827.197** (Windows / macOS), **149.0.7827.196** (Linux) |
| **Vulnerable** | Chrome **OrientationChanged();          // DidUpdateSurfaceAndScreen(previous_original_screen_infos);  // UAF
}
```

`client_->OrientationChanged()` dispatches DOM events **synchronously** on the
renderer's main thread. An attacker-controlled handler can, during that
callback, tear down the very frame that owns this `WidgetBase` β€” e.g. by
removing the hosting `` from the parent document, or by navigating /
closing the frame. That destroys the `WidgetBase` object.

Control then returns into `UpdateSurfaceAndScreenInfo`, which keeps using the
now-freed `this` (`screen_infos_`, `client_`, the call to
`DidUpdateSurfaceAndScreen`). Subsequent access reads/writes freed memory β†’
**use-after-free**.

## The Fix

The patch takes a weak pointer to `this` *before* the re-entrant callback and
bails out if the object was destroyed during it:

```cpp
// third_party/blink/renderer/platform/widget/widget_base.cc  (PATCHED)
  if (orientation_changed) {
    auto weak_this = weak_ptr_factory_.GetWeakPtr();
    client_->OrientationChanged();
    if (!weak_this) {
      return;                               // WidgetBase was destroyed β€” stop.
    }
  }

  client_->DidUpdateSurfaceAndScreen(previous_original_screen_infos);
```

> Commit message: *"Add a weak pointer check after calling
> `client_->OrientationChanged()` because this call can cause the `WidgetBase`
> object to be destroyed."*

---

## How the PoC Triggers It

A renderer widget (`WidgetBase`) is created per **local root frame**. The PoC
embeds a child frame, forces an orientation change for that frame's widget, and
destroys the frame from inside the orientation event handler β€” exactly the
re-entrant free the patch guards against.

`poc.html` implements **three independent trigger strategies**:

1. **Orientation lock + frame removal** β€” the child enters fullscreen and calls
   `screen.orientation.lock()` to force an `orientation_changed` state; its
   `change` handler removes the `` from the parent (frees `WidgetBase`).
2. **Emulated rotation + self-navigation** β€” drives the orientation change via
   responsive/rotation emulation and, in the handler, navigates the frame
   (`location.replace('about:blank')`) to detach the widget mid-callback.
3. **`requestAnimationFrame` re-entry** β€” schedules the teardown on the next
   animation frame so the free lands while the surface/screen update is still
   on the stack, widening the race window.

Each strategy first performs **heap grooming** β€” allocating a batch of
same-sized objects so the freed `WidgetBase` slot is promptly reclaimed by
attacker-controlled data, making the dangling read observable.

## Usage

```bash
# Serve over HTTP (fullscreen + orientation APIs require a secure/served origin)
python -m http.server 8000
# then open http://localhost:8000/poc.html in a target Chrome build
```

For a faithful out-of-process widget (OOPIF), host `victim_frame.html` on a
**different origin** than `poc.html` (e.g. `127.0.0.1:8000` vs `localhost:8000`)
so the child frame gets its own renderer widget. Same-origin still exercises the
code path for local-root subframes.

## Delivering the Orientation Change (important on desktop)

`screen.orientation.lock()` is **mobile-only** β€” on desktop Chrome it throws
`NotSupportedError`, so the page cannot self-trigger `OrientationChanged()`. If
you just open `poc.html` you'll see the frame report *"lock() unsupported on
desktop β€” ARMED and waiting…"* and **no crash** β€” the vulnerable callback never
ran. The orientation change must be delivered by **emulation**:

**Option A β€” automated (recommended):**

```bash
python run_vuln.py "C:\path\to\vulnerable\chrome.exe"   # e.g. 148.0.7778.179
```

`run_vuln.py` uses **only the Python 3 standard library** (no `pip install`): it
ships a tiny built-in WebSocket client, launches the target in an isolated
profile, and flips the emulated `screenOrientation` over CDP
(`Emulation.setDeviceMetricsOverride`) while the frame is armed, then watches for
`Inspector.targetCrashed`.

**Option B β€” manual:** open `poc.html`, open DevTools (`F12`) β†’ device toolbar
(`Ctrl+Shift+M`) β†’ pick a phone β†’ click **Run all**, then repeatedly hit the
**rotate** button. Each rotate delivers the screen-info orientation change.

## Why It Might Not Crash

| Symptom | Cause |
|---|---|
| `lock() unsupported on desktop … ARMED` and nothing happens | No orientation change delivered β€” use Option A or B above. |
| No crash even after rotating | You're on a **patched** build (β‰₯ 149.0.7827.197, or a post-fix 148.0.7778.x). The weak-pointer guard returns early. |
| Crash only sometimes | UAF is a race β€” repeat the flips; an ASAN build makes it deterministic. |

> Note: the exact synchronous re-entrancy that frees the `WidgetBase` is detailed
> only in the restricted Chromium bug 523711130. This PoC models the documented
> `OrientationChanged()` trigger surface from the public fix; reproducing the
> free reliably may require the specific frame arrangement from the original
> report and a vulnerable, ideally ASAN, build.

## Expected Behavior

| Build | Result |
|---|---|
| Chrome **
- Chromium bug 523711130 (restricted)
- Patch: `WidgetBase::UpdateSurfaceAndScreenInfo` weak-pointer guard