CVE-2026-11631
Overview
Background
- `RenderWidgetHostViewAura`
- The Aura-backed implementation of a render widget host view in the browser process that owns platform-specific resources such as
legacy_render_widget_host_HWND_. - `base::WeakPtr`
- A smart pointer that becomes null once the object it references is destroyed, letting callers detect that a
thisobject was freed mid-call. - `weak_ptr_factory_`
- The per-object factory whose
GetWeakPtr()hands outbase::WeakPtrreferences that track the lifetime of the owningRenderWidgetHostViewAura. - `legacy_render_widget_host_HWND_`
- The Windows-only legacy
HWNDmember accessed afterShowImplto hide the widget when the page is not visible.
Root Cause Analysis
Verify before building a PoC
What the commit does not establish: Diff confirms a WeakPtr guard after ShowImpl on Windows only, but not what destroys the view or that web content can trigger it; 'unconditionally' is overstated (shown access is gated by page_visibility). Default web reachability is unsupported.
In RenderWidgetHostViewAura::ShowWithVisibility, the code called window_->Show() and then ShowImpl(page_visibility) before unconditionally touching the Windows-only member legacy_render_widget_host_HWND_. Showing the view can synchronously re-enter code that destroys the RenderWidgetHostViewAura instance, so by the time control returned from ShowImpl the this object could already be freed, yet execution continued into the #if BUILDFLAG(IS_WIN) block that dereferences legacy_render_widget_host_HWND_. The violated invariant is that this must remain valid across the call to ShowImpl before any further member access; nothing guaranteed that after a re-entrant destruction.
The fix captures a base::WeakPtr<RenderWidgetHostViewAura> weak_this from weak_ptr_factory_.GetWeakPtr() immediately before ShowImpl, then checks if (!weak_this) { return; } on Windows, bailing out safely when the view was destroyed and preventing the use-after-free.
legacy_render_widget_host_HWND_) after ShowImpl(page_visibility) without accounting for the possibility that ShowImpl synchronously destroys the RenderWidgetHostViewAura; the fix detects that destruction via a base::WeakPtr guard and returns before any post-ShowImpl member access.Attack Path
- Trigger a show on Windows
Cause a
RenderWidgetHostViewAurato be shown so thatShowWithVisibilityrunswindow_->Show()and thenShowImpl(page_visibility)on a Windows build. - Re-enter and destroy the view
Arrange for the show path to synchronously re-enter browser code that tears down and frees the same
RenderWidgetHostViewAuraduringShowImpl. - Fall through to freed member access
After
ShowImplreturns, execution continues into the#if BUILDFLAG(IS_WIN)block and dereferenceslegacy_render_widget_host_HWND_on the now-freed object. - Exploit the dangling access
Groom the freed allocation so the use-after-free read or
Hide()call operates on attacker-controlled memory, gaining control over browser-process state.
Impact Assessment
RenderWidgetHostViewAura via legacy_render_widget_host_HWND_. Preconditions are a Windows build and the ability to trigger a re-entrant destruction of the view during ShowImpl, which combined with heap grooming can lead to memory corruption and potential sandbox-escaping code execution.Changed Functions
| Function | Change | Notes |
|---|---|---|
ifcontent/browser/renderer_host/render_widget_host_view_aura.cc |
modified |
Files Changed
content/browser/renderer_host/render_widget_host_view_aura.cc
Audit Directions
- Re-entrant destruction after callbacksLook for methods that continue touching
thismembers after calling into functions likeShowImpl,Show, or observer notifications that can synchronously destroy the object. - Platform-guarded tailsScrutinize
#if BUILDFLAG(IS_WIN)and other platform-specific tails that run after a potentially destructive call without abase::WeakPtrlifetime check. - View lifetime across visibility changesAudit
RenderWidgetHostViewAuravisibility and show/hide paths wherewindow_->Show()or similar can trigger nested teardown before later member dereferences.
Patch
From d86edd3226e233b4556c7fc7022042824806e3d9 Mon Sep 17 00:00:00 2001
From: Kartar Singh <kartarsingh@google.com>
Date: Thu, 28 May 2026 09:41:03 -0700
Subject: [PATCH] Prevent Use-After-Free in RenderWidgetHostViewAura::ShowWithVisibility.
Use base::WeakPtr to guard against view destruction during ShowImpl
on Windows builds.
Bug: 516691130
Change-Id: I857c1900ab55f6b0d26e54db35652df4d14d32b8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7883318
Reviewed-by: Jonathan Ross <jonross@chromium.org>
Commit-Queue: Kartar Singh <kartarsingh@google.com>
Cr-Commit-Position: refs/heads/main@{#1637761}
---
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 3c0b9aeb..2575c2a 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1042,8 +1042,15 @@
}
window_->Show();
+
+ base::WeakPtr<RenderWidgetHostViewAura> weak_this(
+ weak_ptr_factory_.GetWeakPtr());
+
ShowImpl(page_visibility);
#if BUILDFLAG(IS_WIN)
+ if (!weak_this) {
+ return;
+ }
if (page_visibility != PageVisibilityState::kVisible &&
legacy_render_widget_host_HWND_) {
legacy_render_widget_host_HWND_->Hide();
Original Bug Report
Potential Use-After-Free in RenderWidgetHostViewAura::ShowWithVisibility on Windows
Project Fortify, an experimental security project, has identified the following potential security issue. If you’re a feature owner CC-ed on this bug, please do your best to review these reports. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.
Overview: A potential Use-After-Free (UAF) vulnerability exists in RenderWidgetHostViewAura::ShowWithVisibility on Windows due to a missing lifetime check. When calling ShowImpl, a nested message loop can be spun during parent or bounds updates of the legacy window, allowing re-entrant window destruction events to delete the view. Upon returning from ShowImpl, the function dereferences members of the already-freed this object.
Affected files:
content/browser/renderer_host/render_widget_host_view_aura.cc
Estimated timestamp from git blame: 2021-01-28
Summary
A potential Use-After-Free (UAF) vulnerability exists in the browser process of Chromium on Windows. The issue is located in RenderWidgetHostViewAura::ShowWithVisibility inside content/browser/renderer_host/render_widget_host_view_aura.cc. When ShowImpl is executed, it can transitively call Win32 windowing APIs that synchronously dispatch messages and spin a nested message loop. If a window close or destruction event is handled during this nested loop, the RenderWidgetHostViewAura instance is deleted. While intermediate functions contain safety guards, the parent method ShowWithVisibility fails to check if the instance is still alive before dereferencing this.
Technical Analysis
In content/browser/renderer_host/render_widget_host_view_aura.cc, the method RenderWidgetHostViewAura::ShowWithVisibility executes the following sequence:
void RenderWidgetHostViewAura::ShowWithVisibility(
PageVisibilityState page_visibility) {
...
window_->Show();
ShowImpl(page_visibility);
#if BUILDFLAG(IS_WIN)
if (page_visibility != PageVisibilityState::kVisible &&
legacy_render_widget_host_HWND_) {
legacy_render_widget_host_HWND_->Hide();
}
#endif // BUILDFLAG(IS_WIN)
}
The call to ShowImpl(page_visibility) eventually routes to NotifyHostAndDelegateOnWasShown, which triggers UpdateLegacyWin() on Windows. Inside UpdateLegacyWin(), Win32 API calls such as ::SetParent or ::SetWindowPos are performed:
if (legacy_render_widget_host_HWND_) {
base::WeakPtr<RenderWidgetHostViewAura> weak_this(
weak_ptr_factory_.GetWeakPtr());
legacy_render_widget_host_HWND_->UpdateParent(GetHostWindowHWND());
if (!weak_this) { return; }
legacy_render_widget_host_HWND_->SetBounds(window_->GetBoundsInRootWindow());
if (!weak_this) { return; }
As noted in the developer comments, both UpdateParent and SetBounds can synchronously dispatch window messages and spin a nested event loop. If a window close/destruction event is dispatched during this nested pump, the re-entrant dispatch reaches RenderWidgetHostViewAura::OnWindowDestroyed, which executes delete this;.
Although UpdateLegacyWin and intermediate functions correctly utilize a WeakPtr guard to return immediately upon destruction, the top-level ShowWithVisibility method lacks this protection. After ShowImpl() returns, the stack unwinds back to ShowWithVisibility, which immediately attempts to read legacy_render_widget_host_HWND_ from the freed this object, resulting in a Use-After-Free.
Because this is a bare stack reference at the call site, MiraclePtr (BackupRefPtr) does not protect against or mitigate this UAF.
Potential Trigger Steps
Note: These are potential, theoretical steps as our automated tooling does not have the capability to run code.
- Open a same-origin popup window using
window.open(). - Force a page visibility transition to a non-visible but active state, such as
PageVisibilityState::kHiddenButPainting(e.g., via tab capture or background Picture-in-Picture). - Race this visibility change with a window close event (e.g., by sending a widget close IPC from a compromised renderer or calling
window.close()on the popup) so that the destruction message is processed during the synchronous Win32 API calls (::SetParentor::SetWindowPos) insideUpdateLegacyWin(). - When the nested loop terminates, the call stack unwinds to
ShowWithVisibility, which dereferences the freedRenderWidgetHostViewAurainstance when evaluatinglegacy_render_widget_host_HWND_.
Suggested Fix
Introduce a WeakPtr check in ShowWithVisibility immediately after returning from ShowImpl to prevent dereferencing the deleted this pointer:
void RenderWidgetHostViewAura::ShowWithVisibility(
PageVisibilityState page_visibility) {
UpdateScreenInfo();
if (!window_->GetLocalSurfaceId().is_valid()) {
window_->AllocateLocalSurfaceId();
SynchronizeVisualProperties(cc::DeadlinePolicy::UseDefaultDeadline(),
window_->GetLocalSurfaceId());
}
base::WeakPtr<RenderWidgetHostViewAura> weak_this(
weak_ptr_factory_.GetWeakPtr());
window_->Show();
ShowImpl(page_visibility);
#if BUILDFLAG(IS_WIN)
if (!weak_this) {
return;
}
if (page_visibility != PageVisibilityState::kVisible &&
legacy_render_widget_host_HWND_) {
legacy_render_widget_host_HWND_->Hide();
}
#endif // BUILDFLAG(IS_WIN)
}
Evaluated with Chrome root at commit: a2bea94528f4bd6cc57739c43fa3bb890b8367d3
Results so far have been promising, but there can be wrong deductions. Feel free to adjust as follows:
- If you are familiar with the severity guidelines, you may adjust the severity.
- If this is a false positive, and there’s no work to be done, please close as WAI.
- If there is work to do here but not a vulnerability, please change the issue type to Task/Bug/FR.
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.