Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInsufficient validation of untrusted input in Navigation
DescriptionInsufficient validation of untrusted input in Navigation
ComponentNavigation
Bug ClassLogic Error
Tracker517148260
Fix commit80366988eaf9 (chromium/src) +13/-2
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-23

Files Changed

  • content/browser/renderer_host/render_frame_host_impl.cc
  • content/public/browser/disallow_activation_reason.h
From 80366988eaf9e38a0bf32220fa757e66ff95e8e2 Mon Sep 17 00:00:00 2001
From: Rakina Zata Amni <rakina@chromium.org>
Date: Mon, 08 Jun 2026 02:14:45 -0700
Subject: [PATCH] Only kill renderer on DidCommit while BFCached if ACKed, evict otherwise

The previous approach of killing the renderer on all DidCommits might
be killing legitimate DidCommit calls that were sent from the renderer
from before the document is actually BFCached. This CL makes it so that
we kill only calls coming from the renderers that already ACKed the
BFCaching. For renderers that haven't we simply just evict the RFH from
BFCache. In both cases we return early and don't continue processing
the DidCommit.

Bug: 520443189, 517148260
Change-Id: I4e3f1518e0d86c506127ee19a709aa5a28bc347c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7901822
Commit-Queue: Rakina Zata Amni <rakina@chromium.org>
Reviewed-by: Fergal Daly <fergal@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1643048}
---

diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index d57c0a6..1c38e9c 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -17263,8 +17263,18 @@
   // kInBackForwardCache state. Trigger a renderer kill if we receive an
   // unexpected DidCommit message.
   if (IsInBackForwardCache()) {
-    bad_message::ReceivedBadMessage(
-        GetProcess(), bad_message::RFH_DID_COMMIT_NAVIGATION_WHILE_BFCACHED);
+    if (render_view_host()->DidReceiveBackForwardCacheAck()) {
+      bad_message::ReceivedBadMessage(
+          GetProcess(), bad_message::RFH_DID_COMMIT_NAVIGATION_WHILE_BFCACHED);
+    } else {
+      // The renderer might not have realized that it's in BFCache when it sent
+      // the DidCommitNavigation call, since we haven't received the BFCache
+      // ACK. In this case, just evict from BFCache instead of killing the
+      // renderer.
+      IsInactiveAndDisallowActivation(
+          DisallowActivationReasonId::kDidCommitNavigation);
+    }
+    // Return early in any case.
     return;
   }
 
diff --git a/content/public/browser/disallow_activation_reason.h b/content/public/browser/disallow_activation_reason.h
index 1ff1f7ed..f0c9fed 100644
--- a/content/public/browser/disallow_activation_reason.h
+++ b/content/public/browser/disallow_activation_reason.h
@@ -65,6 +65,7 @@
   kIndexedDBTransactionIsOngoingAndBlockingOthers = 41,
   kBrowserInitiatedErrorPage = 42,
   kDidChangeOpener = 43,
+  kDidCommitNavigation = 44,
   // New entries go above here. New entries should be added to
   // tools/metrics/histograms/enums.xml .
   kMinEmbedderDisallowActivationReason = 2 << 16,
Loading diff…

Original Bug Report

reported by vm...@google.com

Site Isolation Bypass via DidCommitProvisionalLoad on BFCached Subframes

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 logical vulnerability in Back-Forward Cache (BFCache) navigation commit handling potentially allows a compromised renderer to bypass Site Isolation boundaries. By sending a synthetic synchronous commit IPC to a cached subframe, the renderer can manipulate the session history state of a cross-origin page in the foreground. This can result in spoofing the frame’s origin or injecting attacker-controlled content.

Affected files:

  • content/browser/renderer_host/render_frame_host_impl.cc
  • content/browser/renderer_host/navigation_entry_impl.cc
  • content/browser/renderer_host/navigation_controller_impl.cc
  • content/browser/renderer_host/frame_navigation_entry.cc

Estimated timestamp from git blame: 2020-06-10

Description

A potential logic vulnerability exists in Chromium’s navigation and Back-Forward Cache (BFCache) state handling. Under specific conditions, a compromised renderer process can exploit this flaw to overwrite or inject cross-origin session history state (FrameNavigationEntry) belonging to a foreground page, potentially leading to a Site Isolation bypass.

Root Cause Analysis

  1. Message Filtering in Release Builds: The mojom::FrameHost::DidCommitProvisionalLoad IPC is dispatched to RenderFrameHostImpl::DidCommitNavigation. The browser-side BackForwardCacheMessageFilter::WillDispatch does not discard these messages in release builds under default logging/dumping policies. Inside RenderFrameHostImpl::DidCommitNavigation (in content/browser/renderer_host/render_frame_host_impl.cc), the assertion preventing navigation commits while in the back-forward cache is debug-only:

    DCHECK(!IsInBackForwardCache());
    

    In production release builds, this assertion is compiled out, allowing the commit to proceed.

  2. Subframe Owner Retention: When a page enters the BFCache, the top-level main frame’s owner_ is cleared. However, nested subframe RenderFrameHostImpl objects retain their owner_ pointers (referencing their parent FrameTreeNode), meaning validation checks such as CHECK(owner_) continue to pass.

  3. Synchronous Commit Route: If the subframe was left unnavigated prior to entering the BFCache, is_on_initial_empty_document_ is true. By sending a commit to about:blank, the renderer satisfies the conditions for IsInitialSynchronousAboutBlankCommit and routes the execution along the synchronous commit path, generating a synthetic NavigationRequest in the browser.

  4. Targeting Active Controller: Since the cached subframe remains associated with the active tab’s FrameTree, calling Navigator::DidNavigate routes the commit to the active NavigationControllerImpl of the foreground tab (which represents the victim’s cross-origin page).

  5. FrameNavigationEntry Confusion: In NavigationEntryImpl::AddOrUpdateFrameEntry, the parent node of the BFCached subframe is resolved via GetTreeNode(FrameTreeNode::From(frame_tree_node->parent())). Because the parent is a main frame, MatchesFrame incorrectly matches it against the root node of the active foreground page’s NavigationEntry. The browser then matches the subframe’s unique name against the active page’s subframes, allowing the attacker to overwrite the victim’s FrameNavigationEntry fields (e.g., committed_origin_, site_instance_, page_state_) or append a new entry.

Suggested / Potential Attack Steps (Conceptual)

Note: These steps are based on static code analysis; our tooling does not currently run executable proof-of-concept code.

  1. A compromised renderer process representing an attacker-controlled origin (e.g., https://evil.com) creates a subframe via CreateChildFrame with a unique name matching a target subframe of a victim site (e.g., https://victim.com).
  2. The attacker leaves this subframe on its initial empty document.
  3. The main frame navigates to https://victim.com, causing the evil.com page to enter the BFCache.
  4. The compromised renderer sends a DidCommitProvisionalLoad IPC to the cached subframe for about:blank with PAGE_TRANSITION_AUTO_SUBFRAME and attacker-specified sequence numbers/page state.
  5. The active victim.com page’s subframe history entry is modified or appended with the attacker’s site instance and page state.

Convert the debug-only assertion in RenderFrameHostImpl::DidCommitNavigation into a security-critical check to safely discard unexpected commits from cached frames in release builds:

if (IsInBackForwardCache()) {
  bad_message::ReceivedBadMessage(GetProcess(), bad_message::RFH_COMMIT_WHILE_CACHED);
  return;
}

Additionally, ensure that BackForwardCacheMessageFilter strictly rejects or triggers eviction upon receiving any unexpected navigation-related IPCs while the document is cached.

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