CVE-2026-79052
Overview
Files Changed
ui/aura/window_event_dispatcher.cc
Patch
From 7b842f1861b4deb1e1138eca555f56338d23b41c Mon Sep 17 00:00:00 2001
From: Mitsuru Oshima <oshima@chromium.org>
Date: Mon, 20 Jul 2026 18:54:20 -0700
Subject: [PATCH] Block the deletion of root window in OnWindowHidden
The scenario in the bug should never happen. (It would cause a
lot of other types of problems)
Fixed: 517518019
Change-Id: I5610b3b2366746a1c8511f029444f809eb5a5d39
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8126836
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
Commit-Queue: Mitsuru Oshima <oshima@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1665117}
---
diff --git a/ui/aura/window_event_dispatcher.cc b/ui/aura/window_event_dispatcher.cc
index 002e39e2..35fd163f 100644
--- a/ui/aura/window_event_dispatcher.cc
+++ b/ui/aura/window_event_dispatcher.cc
@@ -379,6 +379,9 @@
if (invisible->Contains(old_dispatch_target_))
old_dispatch_target_ = nullptr;
+ // Block the deletion of the root window, its host thus this dispatcher.
+ aura::Window::ScopedDeleteBlocker blocker(host_->window());
+
// Cleaning up gesture state may end up destroying the hidden window. We use a
// weak pointer to detect this.
base::WeakPtr<aura::Window> invisible_weak = invisible->GetWeakPtrAsWindow();
Original Bug Report
Potential Use-After-Free in WindowEventDispatcher::OnWindowHidden via reentrant 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 has been identified in the browser process within WindowEventDispatcher::OnWindowHidden. Synchronous gesture cleanup can trigger a nested event loop that synchronously destroys the dispatcher, leading to a UAF when member variables are accessed after the reentrant call returns.
Affected files:
ui/aura/window_event_dispatcher.cc
Estimated timestamp from git blame: 2013-11-26
Description
A potential Use-After-Free (UAF) vulnerability exists in ui/aura/window_event_dispatcher.cc. The function WindowEventDispatcher::OnWindowHidden invokes invisible->CleanupGestureState(). While it guards the target window with a weak pointer (invisible_weak), it lacks any self-liveness check or weak pointer guard for the WindowEventDispatcher instance itself (this).
// ui/aura/window_event_dispatcher.cc
base::WeakPtr<aura::Window> invisible_weak = invisible->GetWeakPtrAsWindow();
invisible->CleanupGestureState(); // <--- Re-enters and can synchronously free 'this'
if (reason != WINDOW_MOVING) {
client::CaptureClient* capture_client =
client::GetCaptureClient(host_->window()); // <--- Potential UAF read of host_
Window* capture_window =
capture_client ? capture_client->GetCaptureWindow() : nullptr;
if (!invisible_weak || invisible->Contains(event_dispatch_target_)) {
event_dispatch_target_ = nullptr; // <--- Potential UAF write to event_dispatch_target_
}
...
}
During CleanupGestureState(), active touch points are cancelled, which can synchronously dispatch synthetic touch-cancelled events. On desktop platforms (such as Linux/Ozone/X11 and Windows), an event handler processing this event can synchronously close the top-level widget (e.g., via Widget::CloseNow()). This triggers a synchronous teardown sequence where the WindowTreeHost destroys the WindowEventDispatcher (this).
Upon return from CleanupGestureState(), this has been deallocated, but the code proceeds to dereference this->host_ and perform writes to this->event_dispatch_target_, resulting in a UAF read and write inside the privileged browser process.
Potential Trigger Steps
Note: Our analysis tool does not currently have the capability to run code or execute a live proof of concept; therefore, these are theoretical, potential steps to demonstrate reachability.
- A compromised renderer process establishes a cross-origin subframe and registers active touch state within its boundaries.
- The renderer detaches the subframe, triggering
OnWindowRemovingFromRootWindowand subsequentlyWindowEventDispatcher::OnWindowHiddenon the browser UI thread. OnWindowHiddeninvokesinvisible->CleanupGestureState(), which generates and synchronously dispatches a synthetic touch-cancelled event.- A registered event handler on the target chain processes the cancellation and synchronously calls
Widget::CloseNow()on the top-level widget. - The host destroys the dispatcher synchronously, returning its memory slot to PartitionAlloc.
- Control returns to
OnWindowHidden, where the freed dispatcher memory is accessed when queryinghost_->window()and writing toevent_dispatch_target_.
Suggested Fix
Add a self-liveness check using base::WeakPtr to ensure the WindowEventDispatcher is still valid after performing gesture cleanup:
base::WeakPtr<aura::Window> invisible_weak = invisible->GetWeakPtrAsWindow();
base::WeakPtr<WindowEventDispatcher> weak_this = weak_ptr_factory_.GetWeakPtr();
invisible->CleanupGestureState();
if (!weak_this)
return;
Evaluated with Chrome root at commit: 5133b93d189b383c37805b1cf3a9d2dbfe8d7379
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.