CVE-2026-12035
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifui/views/widget/desktop_aura/desktop_window_tree_host_win.cc |
modified | |
ifui/views/win/hwnd_message_handler.cc |
modified |
Files Changed
ui/views/widget/desktop_aura/desktop_window_tree_host_win.ccui/views/win/hwnd_message_handler.cc
Patch
From 4dd1788994966b0c0f8a72ea5f150680f4b447bf Mon Sep 17 00:00:00 2001 From: David Bienvenu <[email protected]> Date: Fri, 05 Jun 2026 09:04:17 -0700 Subject: [PATCH] win: Handle window closing during move Use weak refs to handle window closing during monitor change. Bug: 520210566 Change-Id: I7f9f218f88ef8e22e3dcffc9afa9d290a6af3fb9 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7905269 Reviewed-by: Keren Zhu <[email protected]> Commit-Queue: David Bienvenu <[email protected]> Cr-Commit-Position: refs/heads/main@{#1642376} --- diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc index 5b1aacd9..9332b09 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc @@ -1183,7 +1183,11 @@ // Adding/removing a monitor, or changing the primary monitor can cause a // WM_MOVE message before `OnDisplayChanged()`. Without this call, we would // DCHECK due to stale `DisplayInfo`s. See https:://crbug.com/1413940. + auto weak_ptr = GetWeakPtr(); display::win::GetScreenWin()->UpdateDisplayInfosIfNeeded(); + if (!weak_ptr) { + return; + } CheckForMonitorChange(); OnHostMovedInPixels(); } diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc index 24901df..d87a944 100644 --- a/ui/views/win/hwnd_message_handler.cc +++ b/ui/views/win/hwnd_message_handler.cc @@ -2382,7 +2382,11 @@ } void HWNDMessageHandler::OnMove(const gfx::Point& point) { + auto ref = msg_handler_weak_factory_.GetWeakPtr(); delegate_->HandleMove(); + if (!ref) { + return; + } SetMsgHandled(FALSE); }
Original Bug Report
Potential Browser UAF in DesktopWindowTreeHostWin::HandleMove during DisplayObserver notification
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 the Windows browser process when display topology or work area updates synchronously close a widget. During DesktopWindowTreeHostWin::HandleMove(), a synchronous display notification can trigger the immediate closure and deletion of the active widget, leaving the stack ’this’ pointer dangling during subsequent member accesses.
Affected files:
ui/views/widget/desktop_aura/desktop_window_tree_host_win.ccui/views/win/hwnd_message_handler.cc
Estimated timestamp from git blame: 2024-01-02
Root Cause Analysis
In ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc, the function DesktopWindowTreeHostWin::HandleMove() invokes display::win::GetScreenWin()->UpdateDisplayInfosIfNeeded() without any subsequent liveness or weak pointer checks on this:
// ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc:1178-1185
void DesktopWindowTreeHostWin::HandleMove() {
// Adding/removing a monitor, or changing the primary monitor can cause a
// WM_MOVE message before `OnDisplayChanged()`. Without this call, we would
// DCHECK due to stale `DisplayInfo`s. See https:://crbug.com/1413940.
display::win::GetScreenWin()->UpdateDisplayInfosIfNeeded(); // <-- Can synchronously destroy 'this'
CheckForMonitorChange(); // <-- UAF read/write
OnHostMovedInPixels(); // <-- UAF virtual call
}
When a display configuration change occurs (e.g., changing the primary monitor or work area boundaries), the OS dispatches a synchronous WM_MOVE message to all top-level windows (including notification popups). This message is received by HWNDMessageHandler::OnMove and delegated to DesktopWindowTreeHostWin::HandleMove().
Inside HandleMove(), the call to UpdateDisplayInfosIfNeeded() triggers a synchronous display observer update loop (change_notifier_.NotifyDisplaysChanged()).
On Windows, DesktopMessagePopupCollection (defined in ui/message_center/views/desktop_message_popup_collection.cc) is registered as an active DisplayObserver. When the display layout changes, DesktopMessagePopupCollection::OnDisplayMetricsChanged is synchronously invoked, which calls ResetBounds() -> ClosePopupsOutsideWorkArea().
If the notification popup currently executing the HandleMove() method is now outside the visible work area, it is synchronously closed via GetWidget()->CloseNow(). This completely deallocates and deletes the underlying DesktopWindowTreeHostWin and its HWNDMessageHandler on the heap.
Upon returning from UpdateDisplayInfosIfNeeded(), control resumes in HandleMove(), but the stack this pointer is now dangling. This results in:
- A Use-After-Free read/write in
CheckForMonitorChange()when querying the window and updatinglast_nearest_display_. - A Use-After-Free virtual call in
OnHostMovedInPixels()when iterating over theobservers_list. - A Use-After-Free write in
HWNDMessageHandler::OnMove()when settingSetMsgHandled(FALSE).
Note: These are potential steps and findings derived from static analysis of the Chromium source tree; our automated tooling does not currently have the capability to execute and validate live exploits.
Sibling Guard Proof of Hazard
The sibling handler HWNDMessageHandler::OnDpiChanged() already implements a weak pointer guard pattern to defend against this exact synchronous destruction scenario:
// ui/views/win/hwnd_message_handler.cc:2017-2021
auto ref = msg_handler_weak_factory_.GetWeakPtr();
display::win::GetScreenWin()->UpdateDisplayInfos();
if (!ref) {
return 0;
}
No such liveness check is present in DesktopWindowTreeHostWin::HandleMove() or HWNDMessageHandler::OnMove().
Potential Steps to Trigger the Issue
- Grant a website permission to display desktop notifications.
- Direct the website to trigger a notification popup (which translates to a top-level
WS_POPUPwindow on Windows). - Alter the system’s screen topology (e.g., unplug a monitor or change the primary monitor’s resolution/identity).
- Windows sends a synchronous
WM_MOVEmessage to the popup, callingHandleMove(). - The display metrics update loop synchronously runs.
DesktopMessagePopupCollectionidentifies that the notification popup is now outside the newly calculated work area boundaries and synchronously callsCloseNow(). - The host and its message handler are destroyed.
- Execution returns to the call stack in
HandleMove()andOnMove(), triggering UAF access on the freed objects.
Suggested Fix
Introduce a base::WeakPtr liveness check inside both HWNDMessageHandler::OnMove() and DesktopWindowTreeHostWin::HandleMove() to safely abort execution if the widget is synchronously destroyed during the display information update.
Specifically, we can add a weak factory or leverage the message handler’s existing weak factory to track liveness. For example, in HWNDMessageHandler::OnMove():
void HWNDMessageHandler::OnMove(const gfx::Point& point) {
auto ref = msg_handler_weak_factory_.GetWeakPtr();
delegate_->HandleMove();
if (!ref) {
return;
}
SetMsgHandled(FALSE);
}
And in DesktopWindowTreeHostWin::HandleMove():
void DesktopWindowTreeHostWin::HandleMove() {
base::WeakPtr<DesktopWindowTreeHostWin> ref = weak_factory_.GetWeakPtr();
display::win::GetScreenWin()->UpdateDisplayInfosIfNeeded();
if (!ref) {
return;
}
CheckForMonitorChange();
OnHostMovedInPixels();
}
Evaluated with Chrome root at commit: d8b226a3be7c9c1ac9240c09e14698866c82e4ac
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.