Overview

High
Severity
9.6
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in Payments
DescriptionUse after free in Payments
ComponentPayments
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.
Tracker553129531
Fix commitf93f6b65c552 (chromium/src) +11/-1
CWECWE-416 (Use-after-free)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H
CISA KEVNot listed
CreditedGoogle
Reported2026-08-26 (per vendor advisory)
Fix landed2026-09-02 (public git)
Disclosed2026-09-08
Patch gap6 days — fix public in source before the advisory

Background

Modal dialog blocking
When a web-modal dialog is shown, BrowserWindowModalDialogDelegate::SetWebContentsBlocked marks the tab’s WebContents as blocked and, as part of that, tears down HTML fullscreen for the tab.
`ExitFullscreen`
content::WebContents::ExitFullscreen restores the browser window from HTML fullscreen, which on some platforms drives synchronous native window-management messages.
Synchronous WndProc reentry
On Windows, resizing/restoring a window can dispatch WM_WINDOWPOSCHANGED directly into a WndProc handler on the current stack, re-entering browser code before the original call frame returns.
`WeakPtr` + `PostTask`
Binding a method to a base::WeakPtr and posting it to content::GetUIThreadTaskRunner({}) runs it in a later task and cancels it automatically if the target object has been destroyed in the meantime.

Root Cause Analysis

While presenting a modal dialog, the delegate synchronously called web_contents->ExitFullscreen(true) from within the dialog-presentation code path (reached via ShowWebModalDialogViews / TabDialogManager::ShowDialog). Exiting fullscreen can synchronously dispatch native window-management messages (e.g. a direct WndProc WM_WINDOWPOSCHANGED on Windows), which re-enters browser code while the modal dialog presentation call is still unwound on the stack. That reentry can destroy the WebContents and the callers that own the presentation flow — dialog controllers and, in the Payments component, PaymentRequestState — after which the still-executing outer frame continues to touch those freed objects, producing a use-after-free.

The fix defers the fullscreen exit by posting WebContents::ExitFullscreen to the UI thread task runner bound through web_contents->GetWeakPtr(), so it only runs after the current synchronous frame fully unwinds, and is cancelled entirely if the WebContents was torn down first.

Key insight
The single mistake was invoking ExitFullscreen synchronously inside an active modal-dialog presentation frame, allowing native window messages to reentrantly free objects the frame still uses; deferring the call via a posted, WeakPtr-guarded task removes the reentrancy and makes the operation safe against destruction.

Attack Path

  1. Trigger a payment/modal flow in fullscreen A page enters HTML fullscreen and initiates a flow that shows a web-modal dialog (e.g. a Payments UI backed by PaymentRequestState).
  2. Dialog presentation blocks the WebContents Showing the dialog calls SetWebContentsBlocked, which decides to drop fullscreen and calls web_contents->ExitFullscreen(true) synchronously.
  3. Synchronous window message re-enters browser code ExitFullscreen drives a native window-management message (e.g. WM_WINDOWPOSCHANGED via direct WndProc) that runs handlers on the current stack. (inferred: platform-specific to Windows as described in the CL)
  4. Owning objects are destroyed mid-frame The reentrant handling tears down the WebContents and callers such as dialog controllers / PaymentRequestState while the modal presentation frame is still active.
  5. Freed memory is used Control returns to the outer presentation frame, which dereferences the now-freed WebContents/caller objects, causing the use-after-free.

Impact Assessment

An attacker controlling a web page can drive a fullscreen page into a modal-dialog (Payments) flow to free and then reuse browser-process objects, yielding a use-after-free in the privileged browser process. Exploitation of such a UAF into memory corruption or code execution is (inferred) and not demonstrated by the patch; the advisory reports only a use-after-free in Payments and does not indicate exploitation in the wild. Preconditions include the tab being in HTML fullscreen without an AUTOMATIC_FULLSCREEN content-setting allowance and the platform delivering synchronous window messages on fullscreen exit.

Files Changed

  • chrome/browser/ui/web_modal/browser_window_modal_dialog_delegate.cc

Audit Directions

  • Synchronous fullscreen/window-state changes during UI presentation
    Audit other call sites that invoke ExitFullscreen, resize, or restore windows synchronously while a dialog/UI presentation frame is active, since these can reentrantly destroy the owning WebContents.
  • Raw pointer use across potentially-reentrant calls
    Look for code that holds a raw WebContents* or controller pointer across a call capable of running nested message loops or native WndProc handlers, and prefer WeakPtr guards or deferred PostTask.
  • `SetWebContentsBlocked` and modal-dialog teardown paths
    Review other actions taken inside dialog blocking/unblocking (across web_modal delegates) for synchronous side effects that assume the WebContents and caller survive the call.
From f93f6b65c55222664e2c3672a11dc3ee6f81eaec Mon Sep 17 00:00:00 2001
From: Keren Zhu <kerenzhu@chromium.org>
Date: Tue, 01 Sep 2026 17:08:27 -0700
Subject: [PATCH] Defer ExitFullscreen when blocking WebContents for modal dialogs

When BrowserWindowModalDialogDelegate::SetWebContentsBlocked is called
upon showing a modal dialog (e.g. via ShowWebModalDialogViews or
TabDialogManager::ShowDialog), it drops HTML fullscreen for the tab.

Calling ExitFullscreen synchronously can trigger direct WndProc calls
(e.g., WM_WINDOWPOSCHANGED on Windows). This can lead to the
WebContents and caller objects (e.g., dialog controllers,
PaymentRequestState) being destroyed synchronously while modal dialog
presentation is still on the stack, resulting in use-after-free
crashes.

This CL posts a task to the UI thread to defer the call to
ExitFullscreen() using a WeakPtr, ensuring the current synchronous
dialog presentation call frame completely unwinds before fullscreen
exit occurs.

TAG=agy
CONV=bce8c045-c1e7-4d88-a581-ff5b1f83ff3c

Bug: 553700283, 540138836, 553128689, 554558968, 553129531
Change-Id: I48e11121ff1a9e33c05705df1869bd749f05b6ee
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8328511
Reviewed-by: Allen Bauer <kylixrd@chromium.org>
Reviewed-by: Thomas Lukaszewicz <tluk@chromium.org>
Commit-Queue: Keren Zhu <kerenzhu@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1690328}
---
diff --git a/chrome/browser/ui/web_modal/browser_window_modal_dialog_delegate.cc b/chrome/browser/ui/web_modal/browser_window_modal_dialog_delegate.cc
index 96c238d..fd0a7db0 100644
--- a/chrome/browser/ui/web_modal/browser_window_modal_dialog_delegate.cc
+++ b/chrome/browser/ui/web_modal/browser_window_modal_dialog_delegate.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/web_modal/browser_window_modal_dialog_delegate.h"
 
+#include "base/functional/bind.h"
 #include "base/types/to_address.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/devtools/devtools_ui_controller.h"
@@ -20,6 +21,8 @@
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/content_settings/core/common/content_settings_types.h"
 #include "components/web_modal/web_contents_modal_dialog_host.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
 
 DEFINE_USER_DATA(BrowserWindowModalDialogDelegate);
@@ -73,7 +76,14 @@
       if (content_settings->GetContentSetting(
               url, url, ContentSettingsType::AUTOMATIC_FULLSCREEN) !=
           CONTENT_SETTING_ALLOW) {
-        web_contents->ExitFullscreen(true);
+        // Defer exiting fullscreen to prevent synchronous window management
+        // messages (e.g. direct WndProc calls on Windows) from destroying the
+        // WebContents or callers while modal dialog presentation is on the
+        // stack.
+        content::GetUIThreadTaskRunner({})->PostTask(
+            FROM_HERE, base::BindOnce(&content::WebContents::ExitFullscreen,
+                                      web_contents->GetWeakPtr(),
+                                      /*will_cause_resize=*/true));
       }
     }
   }
Loading diff…

Original Bug Report

The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.