Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in Aura
DescriptionUse after free in Aura
ComponentAura
Bug ClassUAF
Tracker497548912
Fix commit54847382f578 (chromium/src) +3/-1
CISA KEVNot listed
CreditedGoogle
Disclosed2026-05-05

Files Changed

  • ui/aura/window.cc
From 54847382f578feb9ac9756600e04f9b1eb55b58d Mon Sep 17 00:00:00 2001
From: Takashi Sakamoto <tasak@google.com>
Date: Mon, 30 Mar 2026 18:01:06 -0700
Subject: [PATCH] Enable CHECK(!is_destroying_) on M149 or newer.

Bug: 497548912
Change-Id: Ie2ac006f546152668524afa8b7e489c5334703c3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7710793
Reviewed-by: Mitsuru Oshima <oshima@chromium.org>
Commit-Queue: Takashi Sakamoto <tasak@google.com>
Cr-Commit-Position: refs/heads/main@{#1607525}
---

diff --git a/ui/aura/window.cc b/ui/aura/window.cc
index c1db2c9..832b4fc 100644
--- a/ui/aura/window.cc
+++ b/ui/aura/window.cc
@@ -187,7 +187,9 @@
 
 Window::~Window() {
   // TODO(crbug.com/461127606): Crash on re-entrant destruction.
-  CHECK(!is_destroying_, base::NotFatalUntil::M149);
+  // TODO(crbug.com/497548912): Continue crashing on re-entrant destruction
+  // on Chrome M149 or newer.
+  CHECK(!is_destroying_);
   is_destroying_ = true;
   WindowOcclusionTracker::ScopedPause pause_occlusion_tracking;
 
Loading diff…

Original Bug Report

reported by vm...@google.com

Potential UAF and RCE via re-entrant aura::Window destruction on Windows

Project Fortify, an experimental security project, has identified the following potential security issue.

Overview: A potential Use-After-Free vulnerability exists in aura::Window on Windows due to a non-fatal re-entrancy guard in its destructor. A nested message loop during destruction can allow a second, re-entrant destruction of the same window, bypassing MiraclePtr and leading to a highly reliable UAF. An attacker could potentially exploit this to achieve Remote Code Execution in the browser process.

Affected files:

  • ui/aura/window.cc
  • content/browser/renderer_host/render_widget_host_view_aura.cc
  • ui/wm/core/transient_window_manager.cc
  • content/browser/renderer_host/legacy_render_widget_host_win.cc

Estimated timestamp from git blame: 2026-01-15

Vulnerability Description

A potential Use-After-Free (UAF) and double-free vulnerability exists in aura::Window::~Window() on Windows. The destructor guards against re-entrant destruction with CHECK(!is_destroying_, base::NotFatalUntil::M149). Because this check is non-fatal in builds prior to M149, it triggers a DumpWithoutCrashing but allows execution to continue.

During window destruction, aura::Window notifies its delegate. For a RenderWidgetHostViewAura (RWHVA), this notification eventually calls LegacyRenderWidgetHostHWND::Destroy(), which invokes the Windows API ::DestroyWindow(). This API synchronously pumps the thread’s message loop, which can process pending IPCs.

If the destruction of the window’s parent is triggered during this nested message loop, the parent will iterate through its transient children and call delete on the child window again. This re-enters the ~Window() destructor.

MiraclePtr (BRP) Bypass

When the inner (re-entrant) destructor executes, it successfully removes the window from its parent’s children_ list, its transient parent’s transient_children_ list, and its delegate’s window_ member. Since all of these are raw_ptrs, clearing them drops the MiraclePtr reference count to zero.

When the inner destructor finishes, operator delete genuinely frees the memory to the allocator (bypassing the BackupRefPtr quarantine). When the nested message loop unwinds, the outer destructor resumes execution using its implicit this pointer—which is an unprotected raw C++ pointer—pointing to the now-freed memory. The outer destructor then iterates over the observers_ list, providing a reliable primitive for virtual call hijacking.

Suggested Attacker Steps

Note: These are potential steps based on static analysis; our tooling does not yet have the ability to run code to produce a working Proof of Concept.

  1. A compromised renderer process creates a popup window, which is initialized as a transient child of the main renderer window.
  2. The renderer sends an IPC to close the popup, triggering delete window_; and entering the “outer” aura::Window::~Window().
  3. The outer destructor notifies the delegate, leading to a call to ::DestroyWindow() on Windows, which pumps the message loop.
  4. During this pump, the attacker triggers the destruction of the main window (e.g., by crashing the renderer or via another IPC).
  5. The main window tears down and calls delete on its transient children, including the popup. This enters the “inner” ~Window() destructor.
  6. The non-fatal CHECK is bypassed. The inner destructor clears all raw_ptr references to the popup and frees the memory.
  7. The attacker sprays the heap via IPCs processed in the still-running message loop, reallocating the freed aura::Window memory with a forged base::ObserverList.
  8. The nested message loop unwinds, and the outer destructor resumes. It iterates the attacker-controlled observers_ list and calls observer.OnWindowDestroying(this).
  9. The attacker hijacks the virtual method call to achieve Remote Code Execution (RCE) in the browser process.

Suggested Fix

The re-entrancy guard in aura::Window::~Window() must be made strictly fatal to prevent the inner destructor from proceeding.

Change:

CHECK(!is_destroying_, base::NotFatalUntil::M149);

To:

CHECK(!is_destroying_);

Alternatively, if telemetry is still required without crashing the whole browser in release builds immediately, use base::ImmediateCrash() or base::debug::Alias to halt the specific execution path once the dump is generated, preventing the destructor from continuing.

Evaluated with Chrome root at commit: a9cbf6e8b275fe4147435aa905f3b7f5a656f5f0


Results from so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; data from false positives will be used to improve accuracy over time. And please feel free to reach out to me directly if you have concerns or feedback on the project.

View on issue tracker