CVE-2026-11638
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifchrome/browser/printing/print_view_manager.cc |
modified |
Files Changed
chrome/browser/printing/print_view_manager.cc
Patch
From 87143bb60c99ee71e5c85c1963e90bdfdfbc613f Mon Sep 17 00:00:00 2001
From: Lei Zhang <thestig@chromium.org>
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 <arthursonzogni@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
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();
Original Bug Report
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.ccchrome/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:
- A UAF read of
print_preview_rfh_followed by a virtual method dispatch (GetProcess()). - Passing a dangling
WebContents*retrieved from the freedWebContentsObserversubobject toPrintPreviewDialogController::PrintPreview. - Executing
PrintPreviewAllowedForTesting(), which is a virtual method call on the freedthisobject.
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:
- Direct the browser to a page that enters webpage-initiated HTML fullscreen.
- Invoke
window.print()to trigger the scripted print preview path. - 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. - When the
PrintViewManageris synchronously destroyed, the function returns and dereferences the danglingthispointer.
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.