Medium chrome Info Disclosure 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInformation leak in Mobile
DescriptionInformation leak in Mobile
ComponentMobile
Sub-componentMobile
Bug ClassInfo Disclosure
Tracker557036053
Fix commit6b575a3f89b3 (chromium/src) +14/-3
CISA KEVNot listed
CreditedAnonymous
Disclosed2026-10-06

Files Changed

  • content/public/android/java/src/org/chromium/content_public/browser/NavigationHandle.java
  • content/browser/android/navigation_handle_proxy.cc
  • chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
From 6b575a3f89b3395c0a52e537e5c25deeb2b22db2 Mon Sep 17 00:00:00 2001
From: Michael Thiessen <[email protected]>
Date: Wed, 09 Sep 2026 10:45:36 -0700
Subject: [PATCH] Update referrer on redirect for Java NavigationHandle

Bug: 557036053
Change-Id: Iae9949d2fde57476ed05d53c1433dc144866f5ed
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8382058
Reviewed-by: Calder Kitagawa <[email protected]>
Reviewed-by: Dave Tapuska <[email protected]>
Commit-Queue: Michael Thiessen <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1694711}
---
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
index a9d53f2..68b69f05 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -84,6 +84,7 @@
 import org.chromium.content_public.browser.NavigationHandle;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.common.ContentFeatures;
+import org.chromium.network.mojom.ReferrerPolicy;
 import org.chromium.ui.base.DeviceFormFactor;
 import org.chromium.ui.base.PageTransition;
 import org.chromium.ui.base.ViewUtils;
@@ -366,7 +367,11 @@
                                                 (Boolean shouldIgnore) -> {
                                                     result.set(shouldIgnore);
                                                 });
-                                navigationHandle.didRedirect(redirectUrl, true);
+                                navigationHandle.didRedirect(
+                                        redirectUrl,
+                                        true,
+                                        /* referrerUrl= */ GURL.emptyGURL(),
+                                        /* referrerPolicy= */ ReferrerPolicy.DEFAULT);
                                 mPanel.getOverlayPanelContent()
                                         .getInterceptNavigationDelegateForTesting()
                                         .shouldIgnoreNavigation(
diff --git a/content/browser/android/navigation_handle_proxy.cc b/content/browser/android/navigation_handle_proxy.cc
index 07c5d41..073dbf03 100644
--- a/content/browser/android/navigation_handle_proxy.cc
+++ b/content/browser/android/navigation_handle_proxy.cc
@@ -78,7 +78,10 @@
   Java_NavigationHandle_didRedirect(
       env, java_navigation_handle_,
       url::GURLAndroid::FromNativeGURL(env, cpp_navigation_handle_->GetURL()),
-      cpp_navigation_handle_->IsExternalProtocol());
+      cpp_navigation_handle_->IsExternalProtocol(),
+      url::GURLAndroid::FromNativeGURL(
+          env, cpp_navigation_handle_->GetReferrer().url),
+      static_cast<jint>(cpp_navigation_handle_->GetReferrer().policy));
 }
 
 void NavigationHandleProxy::DidFinish() {
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/NavigationHandle.java b/content/public/android/java/src/org/chromium/content_public/browser/NavigationHandle.java
index 82cd317..cc813d3e 100644
--- a/content/public/android/java/src/org/chromium/content_public/browser/NavigationHandle.java
+++ b/content/public/android/java/src/org/chromium/content_public/browser/NavigationHandle.java
@@ -210,10 +210,13 @@
      */
     @CalledByNative
     @VisibleForTesting
-    public void didRedirect(GURL url, boolean isExternalProtocol) {
+    public void didRedirect(
+            GURL url, boolean isExternalProtocol, GURL referrerUrl, int referrerPolicy) {
         mUrl = url;
         mIsRedirect = true;
         mIsExternalProtocol = isExternalProtocol;
+        mReferrerUrl = referrerUrl;
+        mReferrerPolicy = referrerPolicy;
 
         takeNavigationStateSnapshot();
     }
Loading diff…

Original Bug Report

reported by [email protected]

Server redirect leaves a stale full referrer in Android external-app intents


Report description

Server redirect leaves a stale full referrer in Android external-app intents


Bug location

Where do you want to report your vulnerability?

Chrome VRP – Report security issues affecting the Chrome browser. See program rules


The problem

Please describe the technical details of the vulnerability

Summary

Chrome for Android exports the start-time referrer of a navigation to an external application after a server redirect, even though Chromium’s authoritative navigation state has sanitized the referrer for the final destination. A same-origin first hop can therefore retain a sensitive source path and query and disclose it to an attacker-controlled Android activity reached through an external protocol.

The attached reproduction uses a synthetic URL token, a Python server, an ordinary Chrome binary, and an installable receiver application. It requires no browser patch, test target, unsafe flag, extension, or privileged Android permission.

Bisect

The introducing change copied the initial referrer into the Java navigation mirror. Redirect notifications continued to update only the target URL and external-protocol bit, leaving the initial referrer available to later Android external-navigation code.

Affected versions and validation

  • Current runtime: Chromium ChromePublic 154.0.8028.0, revision 6cf6556e12ab04141b504a3b98c84bf075039e87, on Android 15/API 35 x86_64.
  • Released runtime: Google Chrome Stable 124.0.6367.219, package com.android.chrome, version code 636771938, on Android 15/API 35 x86_64.
  • Released Stable source: Chromium 152.0.7977.72, revision 026bb13a93d60e7adfefa2bbf58d6f57c2d335cc, contains the complete chain.
  • Official main source: Chromium 155.0.8042.0, revision fc03f4856597274bcf07f89c76e592db5a682d96, also contains the complete chain.
  • Citation tree: Chromium 154.0.8012.0, revision 34a482b3cd98d6d599f43091babae366fb9c3d8e; every cited file matches that revision byte-for-byte.
  • Platforms: the demonstrated sink is Chrome for Android. Android WebView, desktop Chrome, ChromeOS, and iOS are not claimed.

Security boundary and prerequisites

  • An attacker controls an Android application that handles the redirect destination.
  • The victim visits a source URL containing sensitive path or query data and follows a normal link through a same-origin redirect endpoint.
  • The first response redirects to the external destination, and the user confirms opening the receiving application if prompted.
  • The source uses the default strict-origin-when-cross-origin policy or another policy that reduces the referrer for the final destination.
  • The receiver needs no sensitive Android permission; it reads its own launch intent.
  • The user gesture authorizes opening the selected destination. It does not authorize disclosure of referrer data that the effective policy removed.
  • App-link verification and Incognito amplification are not part of the demonstrated claim; the PoC uses a custom scheme.

Source chain / root cause

The following citations are from clean revision 34a482b3cd98d6d599f43091babae366fb9c3d8e.

  1. content/browser/renderer_host/navigation_request.cc:3980-3990 updates the authoritative URL and re-sanitizes the referrer for the redirected target:

    common_params_->url = redirect_info.new_url;
    common_params_->referrer->url = GURL(redirect_info.new_referrer);
    common_params_->referrer = Referrer::SanitizeForRequest(
        common_params_->url, *common_params_->referrer);
    
  2. content/browser/android/navigation_handle_proxy.cc:47-81 gives Java the referrer at navigation start but omits it from the redirect update:

    Java_NavigationHandle_didStart(
        env, java_navigation_handle_,
        url::GURLAndroid::FromNativeGURL(
            env, cpp_navigation_handle_->GetReferrer().url),
        static_cast<jint>(cpp_navigation_handle_->GetReferrer().policy), ...);
    ...
    Java_NavigationHandle_didRedirect(
        env, java_navigation_handle_,
        url::GURLAndroid::FromNativeGURL(env, cpp_navigation_handle_->GetURL()),
        cpp_navigation_handle_->IsExternalProtocol());
    
  3. content/public/android/java/src/org/chromium/content_public/browser/NavigationHandle.java:195-206 changes only the target URL and redirect flags:

    public void didRedirect(GURL url, boolean isExternalProtocol) {
        mUrl = url;
        mIsRedirect = true;
        mIsExternalProtocol = isExternalProtocol;
    }
    
  4. content/public/android/java/src/org/chromium/content_public/browser/NavigationHandle.java:294-312 continues exposing the unchanged referrer fields:

    public GURL getReferrerUrl() {
        return assumeNonNull(mReferrerUrl);
    }
    public @Nullable Referrer getReferrer() {
        GURL referrerUrl = getReferrerUrl();
        ...
        return new Referrer(referrerUrl.getSpec(), getReferrerPolicy());
    }
    
  5. components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateImpl.java:281-298 consumes that Java-cached value after the redirect:

    shouldOverrideUrlLoading(
            redirectHandler,
            escapedUrl,
            ...
            navigationHandle.getReferrer(),
            ...);
    
  6. components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java:1557-1559 forwards the stale URL into the outbound intent path:

    if (!params.getReferrerUrl().isEmpty()) {
        mDelegate.maybeSetPendingReferrer(targetIntent, params.getReferrerUrl());
    }
    
  7. chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java:1468-1471 exposes the value to the destination application:

    intent.putExtra(Intent.EXTRA_REFERRER, Uri.parse(url.getSpec()));
    

The browser has a policy-compliant post-redirect referrer, but the Java mirror and exported intent retain the more permissive start-time value. The missing redirect synchronization crosses the web-to-application boundary.

Steps to reproduce

  1. Place all attached files in one directory on a host with Python 3 and adb.
  2. Follow repro.txt to install poc_external_intent_receiver.apk, start poc_external_intent_server.py, configure adb reverse, and clear the disposable Chromium profile.
  3. Open the synthetic sensitive source URL in Chromium ChromePublic 154.0.8028.0.
  4. Press Follow same-origin redirect into test app and select Referrer Receiver if Android presents a resolver.
  5. Repeat with the origin-policy control exposed by the server.

The receiver source and manifest are included for inspection; the attached APK is directly installable. No browser harness or source modification is used.

Actual result

The receiver obtained the full source URL after the server redirect:

android.intent.extra.REFERRER=http://127.0.0.1:8765/account/callback?state=SYNTHETIC_SECRET_27

The origin-policy control delivered only:

android.intent.extra.REFERRER=http://127.0.0.1:8765/

evidence_external_intent_result.txt records both exact runtime targets and the decisive observations. The attached screenshots preserve the full-query disclosure and origin-only control.

Expected result

The external application should receive the referrer derived from the final redirected target and effective policy. Under the demonstrated default policy it should receive only http://127.0.0.1:8765/, never the sensitive source path or query.

Suggested fix

Extend the JNI redirect notification to carry the current sanitized referrer URL and policy, then update the Java fields before any external-navigation observer consumes the handle. Revalidate the authoritative value immediately before exporting an external intent as defense in depth.

fix_external_intent_referrer_redirect.patch implements the production synchronization change and applies cleanly to citation revision 34a482b3cd98d6d599f43091babae366fb9c3d8e.

Incomplete fix

  • Public bug 497493136 / commit c9b35fcba98cc9986bdd859b2ea97a2ac9314315 carries the initial referrer policy into Java and fixes fallback-tab clobbering. It does not synchronize the referrer URL or policy after a server redirect.
  • The adjacent issue concerns policy loss at initial construction; this report concerns stale state after redirect and disclosure through Intent.EXTRA_REFERRER.

Attachments

Name Description SHA-256
repro.txt Standalone setup, decisive user step, expected observation, control, and cleanup. 6cafb8736e882d5931517ae8296539469d05f13a52e5fac2c37cb0bb78a5be9d
poc_external_intent_server.py Dependency-free Python server implementing the source, redirect, and control. 6244eb24a58e38c42d75cab4eafed5e22d8695001044f1705ea7275f42fc9e1e
poc_external_intent_receiver.apk Installable Android application that displays its launch referrer. 97366a0f22d31fd55a8d4be82cc895dff8be379c0ffa1eff1739740182037b00
poc_external_intent_receiver.java Source for the minimal receiver activity. 43a96300d45a956c235b69a086978598e6fdecae291781b12fd3d559bd18bbf5
poc_external_intent_manifest.xml Android manifest registering the synthetic external scheme. a2e7c3104382428fbdebf49ccc8522ec6a57a5d5c3572ce239d1a97a9b70b154
evidence_external_intent_result.txt Exact runtime versions and full-referrer/origin-only observations. 2c0ed1e82272537b3e2a7cd05272f3e55bd785e5ed2b3c99fa212940a20561fc
evidence_external_intent_leak.png Receiver showing the disclosed synthetic path and query. 4309ebab520eafcb0723f16262118a8f10058ea8dbef5d8e7f34110326f881e3
evidence_external_intent_control.png Matching origin-policy control showing an origin-only referrer. 1e070aa10383a13f35b24382d74e9b0b8d3f940d47518e0faeb38725f113a74c
fix_external_intent_referrer_redirect.patch Proposed redirect referrer synchronization fix. de09cdca3766d7ea9903a3713bb72f45b63af11ca42fae1cd497da4ba72ac911

Impact analysis

Impact

  • An attacker-controlled Android application receives source-path and query data that the web page’s referrer policy removed for the final destination.
  • Exposed URLs can contain OAuth state, invitation or reset capabilities, document identifiers, account names, search queries, or other sensitive navigation data.
  • The disclosure crosses Chrome’s web-to-application boundary through a public intent extra readable by the destination activity without a sensitive permission.

The cause

What version of Chrome have you found the security issue in?

124.0.6367.219 + stable-android

No, it is not related to a crash.

Choose the type of vulnerability

Sensitive data exposure

How would you like to be publicly acknowledged for your report?

Anonymous

View on issue tracker