Critical patch-now ✔︎ verified CVSS 9.6 chrome UAF 📄 Reporter bug report 🔧 Commit mapped

Overview

Critical
Severity
9.6
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in Printing
DescriptionUse after free in Printing
ComponentPrinting
Sub-componentPrinting
Bug ClassUAF
Action tierpatch-now — corruption primitive, web-reachable in default config (confirmed) — upheld by independent review by AI
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.
Independent review by AIConfirmed
Reviewer notes: Diff and commit match the claim. Commit frames the UAF as 'potential'/'apparently'-conditional on WebContents being destroyed synchronously inside ExitFullscreen(); the freed-then-used member access is otherwise accurately described.
A second, independent AI reviewer (not a human) re-derived this analysis from the fixing commit and the vendor advisory, looking for errors.
Tracker517047197
Fix commit87143bb60c99 (chromium/src) +6/-0
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-05-27 (per vendor advisory)
Fix landed2026-05-28 (public git)
Disclosed2026-06-08
Patch gap11 days — fix public in source before the advisory

Background

`PrintViewManager`
the browser-process per-WebContents object that drives the print-preview workflow and is owned by (and lifetime-bound to) its WebContents.
Scripted print preview
a print flow initiated by page JavaScript (window.print()), whose completion is handled by OnScriptedPrintPreviewCallback().
`content::WebContents::ExitFullscreen()`
a browser API that leaves fullscreen and can synchronously run arbitrary nested logic (observers, dialogs), which may in turn tear down the WebContents.
`base::WeakPtr`
a smart pointer that becomes null once the object it references is destroyed, allowing callers to detect a destroyed this.

Root Cause Analysis

The enclosing method (named OnScriptedPrintPreviewCallback() in the commit message, though the @@ hunk header does not show it) calls web_contents()->ExitFullscreen(true) when the contents is in fullscreen, then continues to use members such as PrintPreviewDialogController::GetInstance() afterward. ExitFullscreen() can synchronously trigger destruction of the owning WebContents, which destroys the PrintViewManager (this) because its lifetime is tied to the WebContents. The old code assumed this remained valid across the ExitFullscreen() call and dereferenced members on the next lines, violating the invariant that an object must outlive every use of it.

The fix captures weak_factory_.GetWeakPtr() before the call and, if !weak_this afterward, returns early so no member access occurs on a freed PrintViewManager. This works because the WeakPtr is invalidated the instant this is destroyed, converting a silent use-after-free into a safe early return.

Key insight
The code re-entered its own object after calling ExitFullscreen(), a function that can synchronously destroy the WebContents that owns this; the fix detects that self-destruction with a base::WeakPtr check and bails out before touching any freed member.

Attack Path

  1. Enter fullscreen and start scripted print Page content places the tab in webpage-initiated fullscreen and invokes a scripted print preview so the browser reaches OnScriptedPrintPreviewCallback().
  2. Trigger fullscreen exit Because running the dialog forces an exit from fullscreen, web_contents()->IsFullscreen() is true and ExitFullscreen(true) is called.
  3. Provoke WebContents teardown The fullscreen exit synchronously leads to WebContents destruction, which destroys the owning PrintViewManager (this).
  4. Use-after-free on resume Pre-patch, execution continued past ExitFullscreen() and dereferenced the now-freed PrintViewManager (e.g. via web_contents() / dialog-controller access), a use-after-free in the browser process (exact freed-object reuse and any further primitive are (inferred)).

Impact Assessment

An attacker controlling page content that can enter fullscreen and initiate a scripted print preview can cause the browser-process PrintViewManager to be freed and then used, a use-after-free in a privileged (non-sandboxed) process. The vendor advisory rates this critical; preconditions are a fullscreen tab plus a scripted print, both reachable from ordinary web content, though the specific timing of WebContents destruction inside ExitFullscreen() makes it a conditional path. Any escalation beyond the freed-then-used PrintViewManager the diff demonstrates (controlled reuse, code execution) is (inferred).

Changed Functions

FunctionChangeNotes
if
chrome/browser/printing/print_view_manager.cc
modified

Files Changed

  • chrome/browser/printing/print_view_manager.cc

Audit Directions

  • Self-destroying callouts
    Audit any browser-process method that calls WebContents lifecycle-affecting APIs (ExitFullscreen, Close, dialog/observer dispatch) and then keeps using this or web_contents() without a WeakPtr re-check.
  • Observer/owner coupling
    Look for objects whose lifetime is bound to WebContents that invoke synchronous callbacks capable of re-entering and destroying that WebContents.
  • Nested message loops and dialogs
    Review code that runs modal dialogs or nested loops mid-method, since these can destroy the enclosing object before control returns.
From 87143bb60c99ee71e5c85c1963e90bdfdfbc613f Mon Sep 17 00:00:00 2001
From: Lei Zhang <[email protected]>
Date: Thu, 28 May 2026 12:08:39 -0700
Subject: [PATCH] Printing: Avoid a potential UAF in PrintViewManager

PrintViewManager::OnScriptedPrintPreviewCallback() calls
content::WebContents::ExitFullscreen(). Apparently this can trigger
WebContents destruction which then leads to PrintViewManager. Check for
this case using base::WeakPtr and return early.

Bug: 517047197
Change-Id: Ibc7561b1e16fa8f8b3150a45eb1568dae48cc61d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7879647
Reviewed-by: Arthur Sonzogni <[email protected]>
Commit-Queue: Lei Zhang <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1637861}
---

diff --git a/chrome/browser/printing/print_view_manager.cc b/chrome/browser/printing/print_view_manager.cc
index 03fe973..e15499a9 100644
--- a/chrome/browser/printing/print_view_manager.cc
+++ b/chrome/browser/printing/print_view_manager.cc
@@ -420,7 +420,13 @@
   // Running a dialog causes an exit to webpage-initiated fullscreen.
   // https://crbug.com/41322524
   if (web_contents()->IsFullscreen()) {
+    // Return early if `this` got destroyed inside ExitFullscreen().
+    // https://crbug.com/517047197
+    auto weak_this = weak_factory_.GetWeakPtr();
     web_contents()->ExitFullscreen(true);
+    if (!weak_this) {
+      return;
+    }
   }
 
   auto* dialog_controller = PrintPreviewDialogController::GetInstance();
Loading diff…

Original Bug Report

reported by [email protected]

Potential Use-After-Free in PrintViewManager::OnScriptedPrintPreviewCallback via ExitFullscreen

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 due to the synchronous destruction of PrintViewManager inside OnScriptedPrintPreviewCallback. Calling web_contents()->ExitFullscreen(true) can spin the message loop, allowing re-entrant tasks to destroy the owning WebContents and the PrintViewManager. Subsequent execution continues without WeakPtr validation, leading to virtual method calls on the freed object.

Affected files:

  • chrome/browser/printing/print_view_manager.cc
  • chrome/browser/printing/print_view_manager.h

Estimated timestamp from git blame: 2017-06-12

Root Cause Analysis

PrintViewManager is a content::WebContentsUserData<PrintViewManager>, meaning its lifetime is bound synchronously to the lifetime of its owning WebContents.

In PrintViewManager::OnScriptedPrintPreviewCallback (chrome/browser/printing/print_view_manager.cc), the code attempts to exit webpage-initiated fullscreen before showing the print preview:

void PrintViewManager::OnScriptedPrintPreviewCallback(
    content::GlobalRenderFrameHostId rfh_id,
    bool should_proceed) {
  ...
  if (web_contents()->IsFullscreen()) {
    web_contents()->ExitFullscreen(true);   // <--- May synchronously destroy WebContents and |this|
  }

  auto* dialog_controller = PrintPreviewDialogController::GetInstance();
  CHECK(dialog_controller);
  mojom::RequestPrintPreviewParams params;
  params.is_modifiable = !print_preview_rfh_->GetProcess()->IsPdf();   // UAF read/call of print_preview_rfh_
  dialog_controller->PrintPreview(web_contents(), params);             // UAF read of web_contents()
  PrintPreviewAllowedForTesting();                                     // Virtual call on freed |this|
}

When web_contents()->ExitFullscreen(true) is called, it triggers WebContentsImpl::ExitFullscreenMode, which invokes the delegate’s ExitFullscreenModeForTab. On multiple platforms, this transition can dispatch synchronous window messages or spin a nested message loop (e.g., to process OS-level fullscreen transitions).

If a destructive event—such as a tab closure or frame detachment request—is processed while the nested loop is spinning, the WebContents and the associated PrintViewManager are synchronously deleted. When the call stack unwinds back to OnScriptedPrintPreviewCallback, the this pointer is dangling.

Potential Impact

Because there is no WeakPtr validation following ExitFullscreen, multiple Use-After-Free code paths are reachable:

  1. A UAF read of print_preview_rfh_ followed by a virtual method dispatch (GetProcess()).
  2. Passing a dangling WebContents* retrieved from the freed WebContentsObserver subobject to PrintPreviewDialogController::PrintPreview.
  3. Executing PrintPreviewAllowedForTesting(), which is a virtual method call on the freed this object.

If an attacker can reclaim the freed PrintViewManager heap slot with controlled data, the virtual method dispatches could potentially be hijacked to achieve arbitrary code execution in the context of the unsandboxed browser process (Sandbox Escape).

Note: Our static analysis is based on tracing code paths; our tooling agent does not currently have the capability to run code or verify this via a functional Proof of Concept (PoC).

Suggested Potential Exploit Steps

An attacker seeking to trigger this behavior would potentially follow these steps:

  1. Direct the browser to a page that enters webpage-initiated HTML fullscreen.
  2. Invoke window.print() to trigger the scripted print preview path.
  3. During the synchronous fullscreen exit inside OnScriptedPrintPreviewCallback, arrange for a re-entrant task (such as a tab closure request) to be processed by the message loop.
  4. When the PrintViewManager is synchronously destroyed, the function returns and dereferences the dangling this pointer.

Suggested Remediation

Introduce a WeakPtr check to safely abort execution if the PrintViewManager is destroyed during ExitFullscreen:

base::WeakPtr<PrintViewManager> weak_this = weak_factory_.GetWeakPtr();
if (web_contents()->IsFullscreen()) {
  web_contents()->ExitFullscreen(true);
}
if (!weak_this) {
  return;
}

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.

View on issue tracker