High watch CVSS 8.3 chrome UAF 📄 Reporter bug report 🔧 Commit mapped

Overview

High
Severity
8.3
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in Browser
DescriptionUse after free in Browser
ComponentBrowser
Bug ClassUAF
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.
Tracker537105664
Fix commitefb8b71e56b1 (chromium/src) +6/-0
CWECWE-416 (Use-after-free)
CVSS vectorCVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H
CISA KEVNot listed
CreditedGoogle
Reported2026-07-21 (per vendor advisory)
Fix landed2026-08-15 (public git)
Disclosed2026-09-01
Patch gap17 days — fix public in source before the advisory

Background

`BrowserView`
the Views-based container for a Chrome browser window’s UI, owned indirectly by the Browser/window object whose lifetime it shares.
`Widget::Show()`
the Views call that makes a window visible, which on some platforms (e.g. Windows, via HWNDMessageHandler::Show) reaches synchronous OS event-dispatch code such as ::ShowWindow, SetFullscreen, or Activate.
`WeakPtr`/`weak_ptr_factory_`
a mechanism that hands out pointers which automatically become null once the owning object is destroyed, letting a caller detect that this has been freed.
Re-entrant destruction
when a synchronous call dispatches an event whose handler tears down the very object that is still executing on the stack below it.

Root Cause Analysis

BrowserView::Show() called browser_widget_->Show() and then continued to run code on this (notably OnWindowDidShow()) under the assumption that the BrowserView object remained alive across that call. However, Widget::Show() can synchronously reach platform window-management code that dispatches OS events, and an event handler invoked during that dispatch may synchronously close and destroy the browser window — and with it the BrowserView instance. When control returned from browser_widget_->Show(), the remaining statements dereferenced a now-freed this, a classic use-after-free.

The fix captures weak_ptr_factory_.GetWeakPtr() before the Show() call and, immediately after it returns, checks if (!weak_ptr) return;, aborting the function before any further access to freed member state. This works because the WeakPtr is invalidated the instant the BrowserView is destroyed, so the guard reliably distinguishes the destroyed-during-Show() case from the normal case.

Key insight
The single mistake was assuming Widget::Show() is non-re-entrant and cannot destroy its caller, so post-Show() code touched this unconditionally; the fix detects synchronous self-destruction with a WeakPtr guard and returns early instead of using freed memory.

Attack Path

  1. Trigger a window show An attacker or a scripted/automated UI sequence causes a BrowserView to be shown, invoking BrowserView::Show() and reaching browser_widget_->Show().
  2. Enter synchronous platform dispatch Widget::Show() descends into platform code (e.g. HWNDMessageHandler::Show -> SetFullscreen/::ShowWindow/Activate) that synchronously dispatches OS events while the BrowserView frame is still on the stack.
  3. Destroy the window from a handler An event handler running during that dispatch synchronously closes and destroys the browser window, freeing the BrowserView object (this).
  4. Use freed object Control returns to BrowserView::Show(), which pre-patch continued to execute OnWindowDidShow() and other member accesses on the freed this, causing a use-after-free in the browser process. (inferred) Whether this is steerable into a controlled read/write or code execution is not demonstrated by the patch.

Impact Assessment

An attacker who can arrange for a browser window to be destroyed during its own Show() sequence gains a use-after-free of the BrowserView object in the privileged browser process. The advisory classifies this as a use-after-free in the Browser component; any escalation to controlled memory corruption, information disclosure, or code execution is (inferred) and not shown by the patch, and the diff does not indicate exploitation in the wild. The precondition is reaching a synchronous window-destroying event handler nested inside Widget::Show(), which is platform-dependent (the commit cites Windows behavior).

Changed Functions

FunctionChangeNotes
if
chrome/browser/ui/views/frame/browser_view.cc
modified

Files Changed

  • chrome/browser/ui/views/frame/browser_view.cc

Audit Directions

  • Post-call use of `this` across synchronous UI calls
    Audit code that continues to touch member state after Widget::Show(), Activate(), SetFullscreen(), RunMoveLoop(), or other calls that may re-enter platform event dispatch, and confirm a WeakPtr or equivalent liveness guard protects the tail.
  • Re-entrant destruction via event handlers
    Look for browser-process objects whose methods invoke platform or observer callbacks that can close/destroy the owning window, then dereference members afterward without checking for self-destruction.
  • Nested run loops and synchronous dispatch
    Review paths that spin nested message loops or dispatch OS events synchronously (fullscreen transitions, window activation, move loops) for lifetime assumptions about the calling object.
From efb8b71e56b1d5dd3f1bc6e12b5e764ab74a47eb Mon Sep 17 00:00:00 2001
From: Mike Wasserman <[email protected]>
Date: Fri, 14 Aug 2026 22:48:45 -0700
Subject: [PATCH] Fix potential UAF in BrowserView::Show()

Guard against synchronous destruction showing the BrowserView Widget.

Widget::Show() may reach synchronous event dispatch code, e.g. on Win:
 - HWNDMessageHandler::Show -> SetFullscreen / ::ShowWindow / Activate
Event handlers may synchronously close and destroy the browser window.

Mirrors https://crrev.com/c/7897839

Fixed: 537105664
Change-Id: I00546b1c44ad6cf923b061d1a6c39b7322f77c96
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8258613
Commit-Queue: Mike Wasserman <[email protected]>
Reviewed-by: Darryl James <[email protected]>
Auto-Submit: Mike Wasserman <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1680133}
---
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 792b839..f9b1d3d 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1618,7 +1618,13 @@
   if (base::FeatureList::IsEnabled(features::kArtificialUIDelay)) {
     base::PlatformThread::Sleep(features::kViewsUIDelayDuration.Get());
   }
+
+  // Guard against destruction by platform event handlers called during Show().
+  auto weak_ptr = weak_ptr_factory_.GetWeakPtr();
   browser_widget_->Show();
+  if (!weak_ptr) {
+    return;
+  }
 
   OnWindowDidShow();
 
Loading diff…

Original Bug Report

reported by [email protected]

Potential Use-After-Free in BrowserView::Show() due to synchronous window destruction

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 BrowserView::Show() on Windows. When calling browser_widget_->Show(), synchronous native message dispatch can cause the browser window to be destroyed and free the BrowserView instance. Subsequent accesses to the deleted BrowserView instance result in use-after-free reads and writes.

Affected files:

  • chrome/browser/ui/views/frame/browser_view.cc

Estimated timestamp from git blame: 2011-09-19

Potential Vulnerability Details

A potential Use-After-Free (UAF) vulnerability exists in BrowserView::Show() in chrome/browser/ui/views/frame/browser_view.cc. When browser_widget_->Show() is invoked, it delegates to native platform code to display the window. On Windows, this eventually reaches HWNDMessageHandler::Show(), which synchronously dispatches Windows message loops (such as WM_WINDOWPOSCHANGED, WM_SIZE, WM_ACTIVATE) via the native message loop handler.

If a re-entrant callback (such as an observer, native window manager action, or API event) triggers immediate synchronous window destruction during this message dispatch, Widget::CloseNow() or DestroyWindow() is called. Since BrowserWidget owns the BrowserView within its view hierarchy, the deletion of the widget cascades down to invoke ~BrowserView(), deallocating the BrowserView instance (this).

When the synchronous Win32 dispatch stack unwinds and control returns to BrowserView::Show(), the function continues executing with a freed this pointer and no safety checks. It then proceeds to dereference this across several lines, leading to potential memory corruption:

// chrome/browser/ui/views/frame/browser_view.cc:1606-1624
browser_widget_->Show();                                       // Re-entrant native dispatch

browser()->OnWindowDidShow();                                  // Potential UAF read on raw_ptr browser_
...
if (browser_widget_->IsFullscreen() &&                         // Potential UAF read on unique_ptr browser_widget_
    !GetFrameView()->ShouldHideTopUIInFullscreen() && ...      // Potential UAF virtual call via GetFrameView()
    ) { ... }

#if !BUILDFLAG(IS_CHROMEOS)
if (!accessibility_focus_highlight_) {
  accessibility_focus_highlight_ =
      std::make_unique<AccessibilityFocusHighlight>(this);     // Potential UAF write into freed BrowserView slot
}
#endif

Potential Destruction Flow

browser_widget_->Show()
 -> Widget::Show()
  -> HWNDMessageHandler::Show()  [synchronously dispatches WM_ messages]
     [Triggered Close / Destruction Event]
     -> HWNDMessageHandler::HandleDestroyed()
      -> DesktopWindowTreeHostWin::HandleDestroyed()
       -> DesktopNativeWidgetAura::OnHostClosed()
        -> BrowserWidget::OnNativeWidgetDestroyed()
         -> Browser::SynchronouslyDestroyBrowser()
          -> ~Browser()
           -> BrowserView::DeleteBrowserWindow()
            -> browser_widget_.reset()  [deletes BrowserWidget and its child BrowserView]

Suggested Replication Steps

Note: These are potential steps, as our analysis is static and our tooling agent does not have the ability to run functional exploit payloads or compile and execute proof of concepts.

  1. From an extension or page, trigger creation of a new browser window in fullscreen state (e.g., chrome.windows.create({state: "fullscreen"})).
  2. Introduce an observer or state change listener that synchronously closes or deactivates the window during its initial activation/display message loop.
  3. The window destruction path runs synchronously, freeing BrowserView.
  4. When browser_widget_->Show() returns, execution accesses the freed BrowserView memory.

Remediation

To prevent this vulnerability, a base::WeakPtr check should be used immediately after the synchronous browser_widget_->Show() call, matching the pattern already used in BrowserView::SetBounds():

auto weak_ptr = weak_ptr_factory_.GetWeakPtr();
browser_widget_->Show();
if (!weak_ptr) {
  return;
}

Evaluated with Chrome root at commit: bf775e5d75cb9e1767e2cd02cc93efa0077d14a5


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.

View on issue tracker