CVE-2026-13783
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifui/views/controls/menu/menu_controller.cc |
modified |
Files Changed
ui/views/controls/menu/menu_controller.cc
Patch
From b2d9af47f62bf666797d3dc5a3383331a3bb62b9 Mon Sep 17 00:00:00 2001
From: Allen Bauer <kylixrd@chromium.org>
Date: Thu, 28 May 2026 12:35:18 -0700
Subject: [PATCH] Added additional `this` tracking in MenuController:OnMousePressed().
Guards against a11y tools signaling the menu to close during the
notification of the newly hot-tracked button.
Change-Id: Ida8121655c53bc1c4f59c0aaf9a25226ee73c40a
Bug: 516962178
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7882246
Auto-Submit: Allen Bauer <kylixrd@chromium.org>
Commit-Queue: Allen Bauer <kylixrd@chromium.org>
Reviewed-by: David Yeung <dayeung@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1637875}
---
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc
index 10649a65..00f21ac 100644
--- a/ui/views/controls/menu/menu_controller.cc
+++ b/ui/views/controls/menu/menu_controller.cc
@@ -907,13 +907,17 @@
View* view =
forward_to_root->GetEventHandlerForPoint(event_for_root.location());
Button* button = Button::AsButton(view);
+ auto this_ref = AsWeakPtr();
if (hot_button_ != button) {
SetHotTrackedButton(button);
}
+ if (!this_ref) {
+ return true;
+ }
+
// Empty menu items are always handled by the menu controller.
if (!IsViewClass<EmptyMenuMenuItem>(view)) {
- base::WeakPtr<MenuController> this_ref = AsWeakPtr();
bool processed = forward_to_root->ProcessMousePressed(event_for_root);
// This object may be destroyed as a result of a mouse press event (some
// item may close the menu).
Original Bug Report
Potential UAF in MenuController::OnMousePressed due to synchronous deletion in SetHotTrackedButton
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 browser process inside MenuController::OnMousePressed. A call to SetHotTrackedButton can trigger synchronous menu deletion via platform-specific accessibility events before a safeguarding weak pointer is captured. This leads to subsequent operations, including a virtual method call on a stack raw pointer, executing on freed memory.
Affected files:
ui/views/controls/menu/menu_controller.cc
Estimated timestamp from git blame: 2016-03-24
Summary
A potential Use-After-Free (UAF) vulnerability has been identified in the browser process inside MenuController::OnMousePressed (located in ui/views/controls/menu/menu_controller.cc).
When a mouse press event targets a different button inside a menu, the controller invokes SetHotTrackedButton. However, this call occurs before the safeguarding AsWeakPtr() reference (this_ref) is established. Because SetHotTrackedButton dispatches synchronous accessibility events that can cause the menu widget and the controller to be deleted, returning from this call can result in executing subsequent code (including a virtual method call and a heap write) on freed memory.
Vulnerability Analysis
In ui/views/controls/menu/menu_controller.cc, inside MenuController::OnMousePressed:
Button* button = Button::AsButton(view);
if (hot_button_ != button) {
SetHotTrackedButton(button); // Line 911
}
// Empty menu items are always handled by the menu controller.
if (!IsViewClass<EmptyMenuMenuItem>(view)) { // Line 915 - Potential UAF read
base::WeakPtr<MenuController> this_ref = AsWeakPtr(); // Line 916 - Potential UAF read
bool processed = forward_to_root->ProcessMousePressed(event_for_root); // Line 917 - Potential UAF virtual call
if (!this_ref) {
return true;
}
- At line 911, the controller calls
SetHotTrackedButton(button)to update the hot-tracked button. - Within
SetHotTrackedButton(line 3796), an accessibility event is synchronously fired at line 3825:hot_button_->NotifyAccessibilityEventDeprecated(ax::mojom::Event::kSelection, true); - This notification is synchronously dispatched through platform-specific accessibility channels (e.g., using AppKit’s
NSAccessibilityPostNotificationon macOS, or GLib’sg_signal_emit_by_nameon Linux). - An external accessibility listener or client reacting to this event can synchronously trigger actions that close or dismiss the menu (e.g., destroying the widget or window).
- This synchronous destruction deletes the
MenuControllerand its associated view hierarchy (including the targetviewand the root viewforward_to_root). - Once
SetHotTrackedButtonreturns, the execution flow inOnMousePressedcontinues:- Line 915:
IsViewClass<EmptyMenuMenuItem>(view)checks if the now-freedviewis an empty menu item (UAF read). - Line 916:
AsWeakPtr()is called on the deletedMenuController(this), resulting in accessing the freedweak_ptr_factory_member (UAF read). - Line 917:
forward_to_root->ProcessMousePressed(...)executes a virtual method call on the freedMenuHostRootView(UAF virtual call). Sinceforward_to_rootis a stack-allocated raw pointer, it is not protected by MiraclePtr/BackupRefPtr, which could allow a virtual table hijack if the heap is groomed. - Line 927:
current_mouse_event_target_ = forward_to_rootwrites to a member of the deletedthis, causing a UAF heap write.
- Line 915:
Potential Attack Steps
Please note: Since our static-analysis tooling does not have the capability to execute code or run test cases, these are potential/suggested steps to reproduce the vulnerability based on code review.
- Enable system-level accessibility features (or a screen reader) to ensure platform-specific synchronous accessibility events are active.
- Open any Views-based menu containing clickable button elements (e.g., zoom/controls inside the application menu).
- Trigger a mouse-press event on a non-hot-tracked button inside the menu.
- Ensure the resulting accessibility selection notification (
ax::mojom::Event::kSelection) triggers a synchronous callback that dismisses the menu widget (such as by simulating a focus-shift or window state change inside the accessibility handler). - Observe if returning from
SetHotTrackedButtontriggers a crash due to UAF reads/writes inOnMousePressed.
Suggested Fix
To resolve this issue, the AsWeakPtr() reference must be acquired before SetHotTrackedButton is called, and checked immediately after.
--- ui/views/controls/menu/menu_controller.cc
+++ ui/views/controls/menu/menu_controller.cc
@@ -907,11 +907,15 @@
View* view =
forward_to_root->GetEventHandlerForPoint(event_for_root.location());
Button* button = Button::AsButton(view);
+ base::WeakPtr<MenuController> this_ref = AsWeakPtr();
if (hot_button_ != button) {
SetHotTrackedButton(button);
}
+ if (!this_ref) {
+ return true;
+ }
+
// Empty menu items are always handled by the menu controller.
if (!IsViewClass<EmptyMenuMenuItem>(view)) {
- base::WeakPtr<MenuController> this_ref = AsWeakPtr();
bool processed = forward_to_root->ProcessMousePressed(event_for_root);
Evaluated with Chrome root at commit: b1520ef4a76878853a31f0943b565e42060edec8
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.