CVE-2026-17652
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifchrome/browser/ui/views/frame/browser_view.cc |
modified |
Files Changed
chrome/browser/ui/views/frame/browser_view.cc
Patch
From d8c59a2fbbbca18fafb7cc19f2d60682ef348d27 Mon Sep 17 00:00:00 2001 From: Muyao Xu <[email protected]> Date: Tue, 02 Jun 2026 17:48:59 -0700 Subject: [PATCH] [Fullscreen] Fix potential UAF in BrowserView::SetBounds When exiting fullscreen, synchronous window destruction can occur on the UI thread, deleting the BrowserView object and resulting in a UAF issue. Bug: 519262990 Change-Id: I2eb6187f82d316c03c0d9aeeb60eac015d7c7a2d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7897839 Reviewed-by: Mike Wasserman <[email protected]> Commit-Queue: Mike Wasserman <[email protected]> Auto-Submit: Muyao Xu <[email protected]> Cr-Commit-Position: refs/heads/main@{#1640600} --- diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index c5b196b2..9a792d72 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc @@ -1593,7 +1593,11 @@ return; } + auto weak_ptr = weak_ptr_factory_.GetWeakPtr(); exclusive_access_context_->ExitFullscreen(); + if (!weak_ptr) { + return; + } // If the BrowserFrameView has been created, give it a chance to handle the // BrowserWidget's bounds change.
Original Bug Report
Potential Browser-Process Use-After-Free in BrowserView::SetBounds during ExitFullscreen
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::SetBounds due to the lack of a liveness guard after exiting fullscreen. When exiting fullscreen, synchronous widget destruction can occur on the UI thread during nested event loops or message dispatches. Subsequent dereferencing of members on the deleted BrowserView can lead to a browser-process crash or potential arbitrary code execution.
Affected files:
chrome/browser/ui/views/frame/browser_view.cc
Estimated timestamp from git blame: 2024-07-18
Root Cause Analysis
In chrome/browser/ui/views/frame/browser_view.cc:1591-1605, the function BrowserView::SetBounds is implemented as follows:
void BrowserView::SetBounds(const gfx::Rect& bounds) {
if (BrowserWindowFullscreenController::From(browser())->IsForceFullscreen())
return;
exclusive_access_context_->ExitFullscreen();
if (auto* const frame_view = GetFrameView()) {
frame_view->SetFrameBounds(bounds);
} else {
browser_widget_->SetBounds(bounds);
}
}
The call to exclusive_access_context_->ExitFullscreen() triggers a synchronous fullscreen exit transition. Depending on the target platform:
- macOS:
-[NSWindow toggleFullScreen:]is executed inside the Remote Cocoa app shim layer. AppKit spins a nested event-tracking run loop to perform the fullscreen transition animation. - Windows:
FullscreenHandler::SetFullscreentriggers a synchronous Win32::SetWindowPos(hwnd, ..., SWP_FRAMECHANGED)call, which synchronously dispatches window messages.
If a deferred window close request (such as a queued window.close() or posted close task) is processed during this nested run loop or synchronous message dispatch, the BrowserWidget and its associated view hierarchy (including the BrowserView itself) can be synchronously destroyed.
Because BrowserView::SetBounds does not employ a base::WeakPtr or liveness guard after the ExitFullscreen() call, control returns to a dangling this context. The subsequent call to GetFrameView() reads the browser_widget_ unique pointer from the freed BrowserView allocation, leading to a Use-After-Free (UAF). If the deallocated memory is reclaimed by an attacker, the virtual call frame_view->SetFrameBounds(bounds) could be hijacked to achieve arbitrary code execution in the context of the unsandboxed browser process.
Suggested/Potential Trigger Path
Since our tooling agent currently lacks the capability to execute and validate interactive proof-of-concept code, this is a potential trigger path based on static code analysis:
- A compromised renderer opens a same-origin popup window (where
!is_type_normal()is true). - The popup is placed into browser fullscreen (e.g., via F11 or macOS green button), resulting in a fullscreen state mode of
FullscreenMode::kWindowed. - The popup’s renderer queues a window close request (e.g.,
window.close()). - Immediately following this, the renderer issues a
blink::mojom::LocalMainFrameHost::SetWindowRectMojo call. - In the browser process,
ForSecurityDropFullscreenis bypassed because the window is in browser fullscreen (kWindowed), allowing the bounds update to proceed. Browser::SetContentsBoundsforwards the request toBrowserView::SetBounds.BrowserView::SetBoundscallsExitFullscreen(), entering the synchronous platform-specific transition (nested run loop on macOS / synchronous dispatch on Windows).- The queued close request executes during this nested event processing, synchronously deleting the
BrowserWidgetand theBrowserView. - The transition finishes, control returns to
BrowserView::SetBounds, and the subsequent call toGetFrameView()triggers the UAF.
Suggested Fix
The vulnerability can be mitigated by introducing a base::WeakPtr liveness check immediately following the ExitFullscreen() call:
void BrowserView::SetBounds(const gfx::Rect& bounds) {
if (BrowserWindowFullscreenController::From(browser())->IsForceFullscreen())
return;
auto weak_ptr = weak_ptr_factory_.GetWeakPtr();
exclusive_access_context_->ExitFullscreen();
if (!weak_ptr) {
return;
}
if (auto* const frame_view = GetFrameView()) {
frame_view->SetFrameBounds(bounds);
} else {
browser_widget_->SetBounds(bounds);
}
}
Evaluated with Chrome root at commit: 87214e6721f6c34afd9181b80769a24c0c601c50
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.