Medium watch CVSS 7.7 chrome UAF 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
7.7
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in UI
DescriptionUse after free in UI
ComponentUI
Sub-componentWm
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.
Tracker520179360
Fix commit5fd08025f12a (chromium/src) +2/-0
CWECWE-416 (Use-after-free)
CVSS vectorCVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:C/C:H/I:H/A:H
CISA KEVNot listed
CreditedGoogle
Reported2026-06-05 (per vendor advisory)
Fix landed2026-07-23 (public git)
Disclosed2026-08-25
Patch gap33 days — fix public in source before the advisory

Background

`WindowModalityController`
a ui/wm component (window_modality_controller.cc) that observes window changes and enforces modal-dialog behavior, such as activating modal windows and canceling touches.
`aura::Window::ScopedDeleteBlocker`
an RAII object that prevents an aura::Window from being destroyed while it remains in scope.
`kModalKey` property
an aura::client window property whose value (ui::mojom::ModalType) marks a window as modal.
`ActivateWindow`
an activation-client call that focuses/activates a window and can synchronously run observers that may destroy windows.

Root Cause Analysis

In the modality controller’s property-change handler, when a window’s kModalKey became non-kNone and the window was visible, the code called ActivateWindow(window) and then CancelTouchesOnTransientWindowTree(window) on the raw window pointer. ActivateWindow can synchronously dispatch activation/observer callbacks that delete window, after which continued use of window — within ActivateWindow itself or the following CancelTouchesOnTransientWindowTree(window) call — dereferences freed memory, a use-after-free. The invariant that window remains alive for the duration of the activation sequence was not guaranteed.

The fix constructs an aura::Window::ScopedDeleteBlocker blocker(window) before ActivateWindow, so any deletion attempt during activation is blocked until the blocker leaves scope, keeping window valid across both calls.

Key insight
The mistake was activating a window and then reusing its raw pointer without guarding against reentrant deletion during ActivateWindow; the fix pins the window alive with a ScopedDeleteBlocker for the whole activation sequence.

Attack Path

  1. Trigger a modal property change content causes a window’s kModalKey to be set to a non-kNone ModalType while the window is visible, entering the vulnerable branch of the property-change handler.
  2. Activate the window the handler calls ActivateWindow(window), which synchronously runs activation/observer callbacks.
  3. Reentrant deletion one of those callbacks destroys window during activation (the exact deleter is (inferred)), freeing it mid-sequence.
  4. Use freed window execution continues and CancelTouchesOnTransientWindowTree(window) (and/or remaining ActivateWindow work) dereferences the freed window, a use-after-free.

Impact Assessment

The advisory classifies this as a use-after-free in UI. It occurs in the browser-process window manager (ui/wm) when a modal window is deleted reentrantly during activation, so an attacker able to drive modal-window property changes and a coincident deletion could operate on freed memory. Escalation to control-flow hijack or code execution is (inferred), and the advisory does not indicate in-the-wild exploitation.

Files Changed

  • ui/wm/core/window_modality_controller.cc

Audit Directions

  • Raw-pointer reuse across activation/focus calls
    audit ui/wm and aura handlers that keep using a Window* after calling ActivateWindow/Focus/observer-dispatching APIs that can reentrantly delete it.
  • Observer callbacks that delete their subject
    review property-change and event observers that operate on a window/object which downstream synchronous callbacks might destroy, and guard with ScopedDeleteBlocker or weak pointers.
  • Reentrancy in modal/activation flows
    check other modal, transient-window, and activation transitions for sequences that dereference an object after a call capable of triggering nested teardown.
From 5fd08025f12a182600e17849cf6fe8d175dcd7f4 Mon Sep 17 00:00:00 2001
From: Achuith Bhandarkar <[email protected]>
Date: Wed, 22 Jul 2026 17:10:17 -0700
Subject: [PATCH] wm: Use ScopedDeleteBlocker in OnWindowPropertyChanged

`window` should not be deleted during ActivateWindow.

TAG=agy
CONV=45d56d3a-66eb-4f31-b43a-39b4009eabba

Bug: 520179360
Change-Id: I3cb6b8c20d2840f78a1f3e78c2801491a14bdc3b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7975659
Reviewed-by: Mitsuru Oshima <[email protected]>
Commit-Queue: Achuith Bhandarkar <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1666727}
---
diff --git a/ui/wm/core/window_modality_controller.cc b/ui/wm/core/window_modality_controller.cc
index 8204f350..2ff166e2 100644
--- a/ui/wm/core/window_modality_controller.cc
+++ b/ui/wm/core/window_modality_controller.cc
@@ -169,6 +169,8 @@
       window->GetProperty(aura::client::kModalKey) !=
           ui::mojom::ModalType::kNone &&
       window->IsVisible()) {
+    // Block the deletion of `window`.
+    aura::Window::ScopedDeleteBlocker blocker(window);
     ActivateWindow(window);
     CancelTouchesOnTransientWindowTree(window);
   }
Loading diff…

Original Bug Report

reported by [email protected]

Potential Crash in WindowModalityController::OnWindowPropertyChanged during Window Activation

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: An analysis of WindowModalityController::OnWindowPropertyChanged identified a potential re-entrancy path where ActivateWindow can trigger window destruction before CancelTouchesOnTransientWindowTree is called. However, investigation reveals that synchronous destruction under this path is intercepted by ScopedDeleteBlocker, resulting in a safe CHECK crash rather than a Use-After-Free. This report documents the re-entrancy flow and recommends a robust safety improvement.

Affected files:

  • ui/wm/core/window_modality_controller.cc

Estimated timestamp from git blame: 2018-11-14

Description

In ui/wm/core/window_modality_controller.cc:163-175, when the kModalKey property is modified on an already-visible window, WindowModalityController::OnWindowPropertyChanged is triggered:

void WindowModalityController::OnWindowPropertyChanged(aura::Window* window,
                                                       const void* key,
                                                       intptr_t old) {
  if (key == aura::client::kModalKey &&
      window->GetProperty(aura::client::kModalKey) !=
          ui::mojom::ModalType::kNone &&
      window->IsVisible()) {
    ActivateWindow(window);
    CancelTouchesOnTransientWindowTree(window);
  }
}

Calling ActivateWindow(window) synchronously fires activation and deactivation observers via the focus/activation controller. If a deactivation or focus observer attempts to synchronously destroy the window, CancelTouchesOnTransientWindowTree(window) would immediately execute and dereference the potentially freed window pointer.

Root Cause & Existing Safety Mechanisms

An in-depth analysis of the Aura window lifetime management reveals that a Use-After-Free (UAF) is successfully prevented by the following safety barriers:

  1. ScopedDeleteBlocker Protection: When a window property is changed, aura::Window::AfterPropertyChange is executed. This function places a ScopedDeleteBlocker on the stack, incrementing the window’s delete_block_count_ before notifying observers:

    void Window::AfterPropertyChange(const void* key, int64_t old_value) {
      ScopedDeleteBlocker blocker(this);
      for (WindowObserver& observer : observers_)
        observer.OnWindowPropertyChanged(this, key, old_value);
    }
    

    If any observer attempts to synchronously delete window (or its transient parent/child which cascades to window), the destructor Window::~Window() executes the safety check CHECK_EQ(delete_block_count_, 0u). Since delete_block_count_ is non-zero, the browser process safely and immediately terminates with a crash, preventing any UAF condition.

  2. Asynchronous Exo Widget Destruction: For Wayland clients (Exo), widget destruction sequences (e.g., capture-loss or deactivation-triggered closes) use Widget::Close(), which posts an asynchronous task to delete the widget. Thus, synchronous destruction of the native window cannot be initiated by Wayland client actions during activation observer dispatch.

  3. Transient Tree Integrity: If a transient parent window is destroyed under normal conditions, standard destruction observers cleanly update the active window’s parent pointers to nullptr, ensuring no dangling references are left in the tree.

Potential Steps to Trigger the Safe Crash

An attacker/client could theoretically try to trigger a crash (Denial of Service) via the following suggested steps:

  1. From a Wayland client, create and commit an xdg_toplevel window that is mapped and visible.
  2. Configure focus such that activating this window deactivates another window containing an observer that initiates synchronous closure of the transient hierarchy.
  3. Request system modal state on the visible window via zaura_toplevel.set_system_modal or zcr_remote_surface_v2.set_system_modal.
  4. During ActivateWindow, the synchronous deletion path is executed, immediately triggering a safe browser-process crash due to the delete_block_count_ assertion.

Suggested Fix

To make the code robust against re-entrancy hazards and avoid potential denial of service crashes, it is recommended to use aura::WindowTracker to check if the window is still alive after ActivateWindow completes:

void WindowModalityController::OnWindowPropertyChanged(aura::Window* window,
                                                       const void* key,
                                                       intptr_t old) {
  if (key == aura::client::kModalKey &&
      window->GetProperty(aura::client::kModalKey) !=
          ui::mojom::ModalType::kNone &&
      window->IsVisible()) {
    aura::WindowTracker tracker({window});
    ActivateWindow(window);
    if (tracker.Contains(window)) {
      CancelTouchesOnTransientWindowTree(window);
    }
  }
}

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.

View on issue tracker