Low watch CVSS 6.5 chrome Authorization Error 🔧 Commit mapped

Overview

Low
Severity
6.5
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactConfused deputy in Mobile
DescriptionConfused deputy in Mobile
ComponentMobile
Sub-componentFindToolbar
Bug ClassAuthorization Error
Action tierwatch — logic/policy bug — security-relevant, no memory-unsafety
Computed by PatchGap's deterministic exploitability ruler from the fixing commit. patch-now = RCE-class & attacker-reachable in a default config, or exploited in the wild; watch = real security signal below that bar; noise = no security relevance.
Tracker553148673
Fix commit180b36d71ad9 (chromium/src) +22/-28
CWECWE-441
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
CISA KEVNot listed
CreditedGoogle
Reported2026-08-26 (per vendor advisory)
Fix landed2026-08-31 (public git)
Disclosed2026-09-22
Patch gap22 days — fix public in source before the advisory

Background

Confused deputy
a security flaw where a privileged component is tricked into misusing its authority on behalf of a less-privileged caller, here Chrome’s browser process acting on attacker-controlled clipboard content.
`ClipData.Item.coerceToText()`
an Android ClipboardManager API that resolves a clipboard item to a string, including dereferencing content:// URIs, which can force the calling app to read internal resources it has permission to but the source did not.
`Clipboard.getCoercedText()`
Chrome’s wrapper in org.chromium.ui.base.Clipboard (ClipboardImpl) that coerces clipboard text while rejecting untrusted internal URIs, centralizing the confused-deputy protections.
`FindToolbar`
the in-page find bar UI (org.chromium.chrome.browser.findinpage.FindToolbar) whose query EditText handles paste via onTextContextMenuItem().

Root Cause Analysis

The onTextContextMenuItem() handler in FindToolbar handled the android.R.id.paste action by reading the system clipboard directly through ClipboardManager.getPrimaryClip() and calling ClipData.Item.coerceToText() on each item. Because coerceToText() will dereference a content:// URI using the browser’s own permissions, an attacker who placed a crafted URI on the clipboard could induce Chrome to resolve internal/privileged content and paste its contents into the find field — the classic confused-deputy pattern. The invariant violated is that all clipboard coercion in Chrome must pass through the guarded Clipboard/ClipboardImpl path that filters untrusted internal URIs, which FindToolbar bypassed.

The fix routes paste through Clipboard.getInstance().getCoercedText(), so untrusted internal URIs are rejected before any text is produced. It also handles a null result by returning true to consume the event, preventing TextView’s default paste handler from re-running the unguarded coercion as a fallback.

Key insight
The single mistake was coercing clipboard content with the raw Android ClipData.Item.coerceToText() API instead of Chrome’s guarded Clipboard.getCoercedText(), which meant the confused-deputy URI filtering never ran; the fix simply funnels the paste path through the guarded API and consumes the event on a null result.

Attack Path

  1. Plant a malicious clipboard item The attacker arranges for the Android clipboard’s primary clip to hold a crafted content:// URI (or similar item) whose coercion would leak internal resources. (inferred)
  2. Trigger the find bar paste The user (or an automated flow) opens FindToolbar and invokes Paste on the query EditText, dispatching android.R.id.paste to onTextContextMenuItem().
  3. Unguarded coercion runs The handler calls clipData.getItemAt(i).coerceToText(getContext()), causing the browser to dereference the attacker’s URI with its own permissions instead of rejecting it.
  4. Privileged content is surfaced The coerced internal content is written into the find field via text.replace(min, max, builder.toString()), exposing data the attacker’s context could not otherwise read. (inferred)

Impact Assessment

An attacker leveraging clipboard content can turn Chrome’s browser process into a confused deputy, causing it to resolve and surface internal/privileged resources via the find bar paste path, with the precondition that a malicious item is on the clipboard and a paste is performed in FindToolbar. The advisory classifies this as a LogicError / confused deputy in Mobile and states no exploited-in-the-wild status. Any escalation beyond exposing the coerced content into the find field is not demonstrated by the patch. (inferred)

Changed Functions

FunctionChangeNotes
if
chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindToolbar.java
modified

Files Changed

  • chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindToolbar.java

Audit Directions

  • Raw clipboard coercion
    Search for direct uses of ClipData.Item.coerceToText(), ClipboardManager.getPrimaryClip(), or getSystemService(Context.CLIPBOARD_SERVICE) in Java UI code that should instead go through Clipboard/ClipboardImpl.
  • Custom paste handlers
    Audit overrides of onTextContextMenuItem() and TextView paste paths across Chrome’s Android widgets for bypasses of the guarded clipboard API, including missing null-consume handling that lets the default paste re-run.
  • URI-dereferencing deputies
    Look for other spots where the browser resolves content:// or similar URIs from untrusted sources using its own permissions without the internal-URI filtering.
From 180b36d71ad9533a4bddac90ac3ef1fadc0d9b40 Mon Sep 17 00:00:00 2001
From: Charles Cai <[email protected]>
Date: Mon, 31 Aug 2026 15:58:00 -0700
Subject: [PATCH] FindToolbar: Use guarded Clipboard API for paste

FindToolbar previously called ClipData.Item.coerceToText() directly,
bypassing the confused-deputy protections in ClipboardImpl.

Update FindToolbar to use Clipboard.getInstance().getCoercedText()
so untrusted internal URIs are rejected when pasting plain text.
If coerced text is null, consume the event to prevent falling back
to TextView's default paste handler.

Bug: 553148673
Change-Id: Ief6bdcfafa0871f40e3b856f21ba0238cbe3a316
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8324467
Commit-Queue: Charles Cai <[email protected]>
Reviewed-by: Charles Hager <[email protected]>
Reviewed-by: Andrew Grieve <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1689357}
---
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindToolbar.java
index 2ac6b54..f19611a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindToolbar.java
@@ -9,8 +9,6 @@
 
 import android.animation.Animator;
 import android.annotation.SuppressLint;
-import android.content.ClipData;
-import android.content.ClipboardManager;
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.Handler;
@@ -64,6 +62,7 @@
 import org.chromium.components.find_in_page.FindMatchRectsDetails;
 import org.chromium.components.find_in_page.FindNotificationDetails;
 import org.chromium.components.find_in_page.FindResultBar;
+import org.chromium.ui.base.Clipboard;
 import org.chromium.ui.base.UiAndroidFeatureList;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.text.EmptyTextWatcher;
@@ -174,34 +173,29 @@
         @Override
         public boolean onTextContextMenuItem(int id) {
             if (id == android.R.id.paste) {
-                ClipboardManager clipboard =
-                        (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
-                ClipData clipData = clipboard.getPrimaryClip();
-                if (clipData != null) {
-                    // Convert the clip data to a simple string
-                    StringBuilder builder = new StringBuilder();
-                    for (int i = 0; i < clipData.getItemCount(); i++) {
-                        builder.append(clipData.getItemAt(i).coerceToText(getContext()));
-                    }
-
-                    // Identify how much of the original text should be replaced
-                    var text = getText();
-                    assumeNonNull(text);
-                    int min = 0;
-                    int max = text.length();
-
-                    if (isFocused()) {
-                        final int selStart = getSelectionStart();
-                        final int selEnd = getSelectionEnd();
-
-                        min = Math.max(0, Math.min(selStart, selEnd));
-                        max = Math.max(0, Math.max(selStart, selEnd));
-                    }
-
-                    Selection.setSelection(text, max);
-                    text.replace(min, max, builder.toString());
+                String textToPaste = Clipboard.getInstance().getCoercedText();
+                if (textToPaste == null) {
+                    // Consume the paste action to avoid falling back to TextView's default paste.
                     return true;
                 }
+
+                // Identify how much of the original text should be replaced
+                var text = getText();
+                assumeNonNull(text);
+                int min = 0;
+                int max = text.length();
+
+                if (isFocused()) {
+                    final int selStart = getSelectionStart();
+                    final int selEnd = getSelectionEnd();
+
+                    min = Math.max(0, Math.min(selStart, selEnd));
+                    max = Math.max(0, Math.max(selStart, selEnd));
+                }
+
+                Selection.setSelection(text, max);
+                text.replace(min, max, textToPaste);
+                return true;
             }
             return super.onTextContextMenuItem(id);
         }
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.