Low chrome Logic Error 🔧 Commit mapped

Overview

Low
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactPolicy bypass in Chrome for iOS
DescriptionPolicy bypass in Chrome for iOS
ComponentChrome for iOS
Bug ClassLogic Error
Tracker511808800
Fix commitfdb4fcf96972 (chromium/src) +51/-1
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-30

Changed Functions

FunctionChangeNotes
if
ios/chrome/browser/reader_mode/model/reader_mode_tab_helper.mm
modified
TEST_F
ios/chrome/browser/reader_mode/model/reader_mode_tab_helper_unittest.mm
modified

Files Changed

  • ios/chrome/browser/reader_mode/model/reader_mode_tab_helper.mm
  • ios/chrome/browser/reader_mode/model/reader_mode_tab_helper_unittest.mm
From fdb4fcf96972c262ecc007b562ee8ef077312ebe Mon Sep 17 00:00:00 2001
From: Quentin Pubert <qpubert@google.com>
Date: Thu, 21 May 2026 03:39:58 -0700
Subject: [PATCH] [iOS][ReaderMode] Default link forwarding to ReferrerPolicyStrictOriginWhenCrossOrigin

This changes the default ReferrerPolicy used in ReaderModeContentDidCancelRequest from ReferrerPolicyDefault to ReferrerPolicyStrictOriginWhenCrossOrigin. This prevents potential Referrer-Policy bypass and URL/sensitive parameter leaks when navigating to cross-origin destinations from Reader Mode.

Bug: 511808800
Change-Id: Ic3fb923f621a23d447b3fc93f0fe4f8b8be5ca1e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7864202
Reviewed-by: Olivier Robin <olivierrobin@chromium.org>
Commit-Queue: Olivier Robin <olivierrobin@chromium.org>
Auto-Submit: Quentin Pubert <qpubert@google.com>
Commit-Queue: Quentin Pubert <qpubert@google.com>
Cr-Commit-Position: refs/heads/main@{#1634159}
---

diff --git a/ios/chrome/browser/reader_mode/model/reader_mode_tab_helper.mm b/ios/chrome/browser/reader_mode/model/reader_mode_tab_helper.mm
index 5221dc6f..275008d4 100644
--- a/ios/chrome/browser/reader_mode/model/reader_mode_tab_helper.mm
+++ b/ios/chrome/browser/reader_mode/model/reader_mode_tab_helper.mm
@@ -378,7 +378,7 @@
   if (referrer_value) {
     NSURL* referrer_url = [NSURL URLWithString:referrer_value];
     params.referrer.url = net::GURLWithNSURL(referrer_url);
-    params.referrer.policy = web::ReferrerPolicyDefault;
+    params.referrer.policy = web::ReferrerPolicyStrictOriginWhenCrossOrigin;
   }
   params.transition_type = request_info.transition_type;
   web_state_->GetNavigationManager()->LoadURLWithParams(params);
diff --git a/ios/chrome/browser/reader_mode/model/reader_mode_tab_helper_unittest.mm b/ios/chrome/browser/reader_mode/model/reader_mode_tab_helper_unittest.mm
index e5f1c9d..e10a6a4 100644
--- a/ios/chrome/browser/reader_mode/model/reader_mode_tab_helper_unittest.mm
+++ b/ios/chrome/browser/reader_mode/model/reader_mode_tab_helper_unittest.mm
@@ -991,6 +991,56 @@
   EXPECT_EQ(0u, infobar_manager->infobars().size());
 }
 
+// Tests that when Reader Mode cancels a request, the request is forwarded to
+// the navigation manager with the correct
+// ReferrerPolicyStrictOriginWhenCrossOrigin policy.
+TEST_F(ReaderModeTabHelperTest, ReaderModeContentDidCancelRequestForwarding) {
+  web_state()->WasShown();
+  GURL test_url("https://test.url/");
+  LoadWebpage(web_state(), test_url);
+  SetReaderModeState(web_state(), test_url,
+                     ReaderModeHeuristicResult::kReaderModeEligible, "Content");
+  WaitForPageLoadDelayAndRunUntilIdle();
+
+  // Activate Reader Mode.
+  reader_mode_tab_helper()->ActivateReader(
+      ReaderModeAccessPoint::kContextualChip);
+  WaitForAvailableReaderModeContentInWebState(web_state());
+
+  // Ensure the host tab navigation manager has not been called yet.
+  web::FakeNavigationManager* navigation_manager =
+      static_cast<web::FakeNavigationManager*>(
+          web_state()->GetNavigationManager());
+  ASSERT_FALSE(navigation_manager->LoadURLWithParamsWasCalled());
+
+  // Simulate a navigation cancellation with a referrer.
+  NSMutableURLRequest* request = [NSMutableURLRequest
+      requestWithURL:[NSURL URLWithString:@"https://destination.url/"]];
+  [request setValue:@"https://referrer.url/"
+      forHTTPHeaderField:@"Referer"];
+
+  web::WebStatePolicyDecider::RequestInfo request_info(
+      ui::PageTransition::PAGE_TRANSITION_LINK,
+      /*target_frame_is_main=*/true,
+      /*target_frame_is_cross_origin=*/true,
+      /*target_window_is_cross_origin=*/false,
+      /*is_user_initiated=*/true,
+      /*user_tapped_recently=*/true);
+
+  reader_mode_tab_helper()->ReaderModeContentDidCancelRequest(nil, request,
+                                                              request_info);
+
+  // Verify that the host WebState's navigation manager loaded the request
+  // with web::ReferrerPolicyStrictOriginWhenCrossOrigin.
+  EXPECT_TRUE(navigation_manager->LoadURLWithParamsWasCalled());
+  web::NavigationManager::WebLoadParams load_params =
+      navigation_manager->GetLastLoadURLWithParams().value();
+  EXPECT_EQ(GURL("https://destination.url/"), load_params.url);
+  EXPECT_EQ(GURL("https://referrer.url/"), load_params.referrer.url);
+  EXPECT_EQ(web::ReferrerPolicyStrictOriginWhenCrossOrigin,
+            load_params.referrer.policy);
+}
+
 INSTANTIATE_TEST_SUITE_P(
     All,
     ReaderModeTabHelperWithEligibilityTest,
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/ios/chrome/browser/reader_mode/model/reader_mode_tab_helper_unittest.mm b/ios/chrome/browser/reader_mode/model/reader_mode_tab_helper_unittest.mm
index e5f1c9d..e10a6a4 100644
--- a/ios/chrome/browser/reader_mode/model/reader_mode_tab_helper_unittest.mm
+++ b/ios/chrome/browser/reader_mode/model/reader_mode_tab_helper_unittest.mm
@@ -991,6 +991,56 @@
   EXPECT_EQ(0u, infobar_manager->infobars().size());
 }
 
+// Tests that when Reader Mode cancels a request, the request is forwarded to
+// the navigation manager with the correct
+// ReferrerPolicyStrictOriginWhenCrossOrigin policy.
+TEST_F(ReaderModeTabHelperTest, ReaderModeContentDidCancelRequestForwarding) {
+  web_state()->WasShown();
+  GURL test_url("https://test.url/");
+  LoadWebpage(web_state(), test_url);
+  SetReaderModeState(web_state(), test_url,
+                     ReaderModeHeuristicResult::kReaderModeEligible, "Content");
+  WaitForPageLoadDelayAndRunUntilIdle();
+
+  // Activate Reader Mode.
+  reader_mode_tab_helper()->ActivateReader(
+      ReaderModeAccessPoint::kContextualChip);
+  WaitForAvailableReaderModeContentInWebState(web_state());
+
+  // Ensure the host tab navigation manager has not been called yet.
+  web::FakeNavigationManager* navigation_manager =
+      static_cast<web::FakeNavigationManager*>(
+          web_state()->GetNavigationManager());
+  ASSERT_FALSE(navigation_manager->LoadURLWithParamsWasCalled());
+
+  // Simulate a navigation cancellation with a referrer.
+  NSMutableURLRequest* request = [NSMutableURLRequest
+      requestWithURL:[NSURL URLWithString:@"https://destination.url/"]];
+  [request setValue:@"https://referrer.url/"
+      forHTTPHeaderField:@"Referer"];
+
+  web::WebStatePolicyDecider::RequestInfo request_info(
+      ui::PageTransition::PAGE_TRANSITION_LINK,
+      /*target_frame_is_main=*/true,
+      /*target_frame_is_cross_origin=*/true,
+      /*target_window_is_cross_origin=*/false,
+      /*is_user_initiated=*/true,
+      /*user_tapped_recently=*/true);
+
+  reader_mode_tab_helper()->ReaderModeContentDidCancelRequest(nil, request,
+                                                              request_info);
+
+  // Verify that the host WebState's navigation manager loaded the request
+  // with web::ReferrerPolicyStrictOriginWhenCrossOrigin.
+  EXPECT_TRUE(navigation_manager->LoadURLWithParamsWasCalled());
+  web::NavigationManager::WebLoadParams load_params =
+      navigation_manager->GetLastLoadURLWithParams().value();
+  EXPECT_EQ(GURL("https://destination.url/"), load_params.url);
+  EXPECT_EQ(GURL("https://referrer.url/"), load_params.referrer.url);
+  EXPECT_EQ(web::ReferrerPolicyStrictOriginWhenCrossOrigin,
+            load_params.referrer.policy);
+}
+
 INSTANTIATE_TEST_SUITE_P(
     All,
     ReaderModeTabHelperWithEligibilityTest,
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.