Low CVSS 4.3 chrome Input Validation 🔧 Commit mapped

Overview

Low
Severity
4.3
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInsufficient validation of untrusted input in Input
DescriptionInsufficient validation of untrusted input in Input
ComponentInput
Sub-componentA11y
Bug ClassInput Validation
Tracker514072607
Fix commitc03d94e51186 (chromium/src) +60/-29
CWECWE-20 (Improper input validation)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N
CISA KEVNot listed
CreditedGoogle
Reported2026-05-17 (per vendor advisory)
Fix landed2026-05-28 (public git)
Disclosed2026-06-30
Patch gap33 days — fix public in source before the advisory

Changed Functions

FunctionChangeNotes
if
content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
modified

Files Changed

  • content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
From c03d94e511860de8f90c092b28d7253f72a35dac Mon Sep 17 00:00:00 2001
From: Aaron Moss <aaronmoss@google.com>
Date: Thu, 28 May 2026 15:30:27 -0700
Subject: [PATCH] [a11y] Clamp cursor-following to viewport

Ensure that cursor-following cannot be used to scroll outside the
WebView.

Bug: 514072607
Change-Id: I82729ae0837f12f91620adc599c3eff86ff9ef3d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7859114
Reviewed-by: Bo Liu <boliu@chromium.org>
Commit-Queue: Aaron Moss <aaronmoss@google.com>
Cr-Commit-Position: refs/heads/main@{#1638003}
---

diff --git a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
index 17ade2a..4adbbbe6 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapterImpl.java
@@ -1593,8 +1593,10 @@
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA
                 && Build.VERSION.SDK_INT_FULL >= Build.VERSION_CODES_FULL.BAKLAVA_1
                 && ContentFeatureList.sAccessibilityMagnificationFollowsFocus.isEnabled()) {
-            Rect nodePix = fromCssToDevicePix(nodeLeftDip, nodeTopDip, nodeRightDip, nodeBottomDip);
-            if (!nodePix.isEmpty()) {
+            Rect nodePix =
+                    fromViewportDipToViewContentPix(
+                            nodeLeftDip, nodeTopDip, nodeRightDip, nodeBottomDip, containerView);
+            if (nodePix != null && !nodePix.isEmpty()) {
                 containerView.requestRectangleOnScreen(
                         nodePix,
                         /* immediate= */ false,
@@ -1768,23 +1770,49 @@
     }
 
     /**
-     * Converts bounds from CSS pixels to device pixels, accounting for page scale, device scale,
-     * and content Y offset.
+     * Converts bounds from device-independent pixels in viewport space to device pixels in
+     * view-content space, clamped to the visible rectangle of the container view.
      *
-     * @param left left X coordinate in CSS pixels
-     * @param top top Y coordinate in CSS pixels
-     * @param right right X coordinate in CSS pixels
-     * @param bottom bottom Y coordinate in CSS pixels
-     * @return {@link Rect} with the device pixel equivalents of the provided coordinates.
+     * @param left left X coordinate in Blink viewport-relative DIPs
+     * @param top top Y coordinate in Blink viewport-relative DIPs
+     * @param right right X coordinate in Blink viewport-relative DIPs
+     * @param bottom bottom Y coordinate in Blink viewport-relative DIPs
+     * @param containerView view to clamp coordinates to
+     * @return {@link Rect} with the device pixel equivalents of the provided coordinates in
+     *     view-content space, clamped to the visible portion of the container view, or null if the
+     *     bounds do not intersect the visible portion of the container view.
      */
-    private Rect fromCssToDevicePix(float left, float top, float right, float bottom) {
+    private @Nullable Rect fromViewportDipToViewContentPix(
+            float left, float top, float right, float bottom, View containerView) {
+        // Get container view's visible area in view-content coordinates.
+        // Chrome team trial-and-error has determined that (inconsistently with other View
+        // documentation), "top left" in the View#getLocalVisibleRect is in content space rather
+        // than viewport space for the view.
+        Rect visibleRect = new Rect();
+        if (!containerView.getLocalVisibleRect(visibleRect)) {
+            return null; // The container is entirely offscreen.
+        }
+
+        // Scale bounds to device pixels in Android view coordinates.
         RenderCoordinatesImpl coords = mWebContents.getRenderCoordinates();
-        final int topOffset = coords.getContentOffsetYPixInt();
-        return new Rect(
-                (int) coords.fromLocalCssToPix(left),
-                ((int) coords.fromLocalCssToPix(top)) + topOffset,
-                (int) coords.fromLocalCssToPix(right),
-                ((int) coords.fromLocalCssToPix(bottom)) + topOffset);
+        final int topOffset = coords.getContentOffsetYPixInt(); // Offset for Chrome address bar.
+        final float scale = coords.getDeviceScaleFactor();
+        Rect bounds =
+                new Rect(
+                        (int) (left * scale),
+                        (int) (top * scale) + topOffset,
+                        (int) (right * scale),
+                        (int) (bottom * scale) + topOffset);
+
+        // Translate bounds to view-content coordinates by adding Android view scroll. This is a
+        // no-op for Chrome (which always reports zero scroll), but will adjust for WebView scroll.
+        bounds.offset(containerView.getScrollX(), containerView.getScrollY());
+
+        // Clamp to visible area and return clamped bounds in view-content coordinates.
+        if (!bounds.intersect(visibleRect)) {
+            return null; // The bounds are entirely offscreen.
+        }
+        return bounds;
     }
 
     /**
@@ -1810,23 +1838,26 @@
             // Convert caret bounds from CSS pixels to device pixels relative to root view.
             var caretCss = cursorAnchorInfo.insertionMarker;
             Rect caretPix =
-                    fromCssToDevicePix(
+                    fromViewportDipToViewContentPix(
                             caretCss.x,
                             caretCss.y,
                             caretCss.x + caretCss.width,
-                            caretCss.y + caretCss.height);
+                            caretCss.y + caretCss.height,
+                            containerView);
 
-            // Note: `SDK_INT_FULL` added in `BAKLAVA`, hence two checks.
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA
-                    && Build.VERSION.SDK_INT_FULL >= Build.VERSION_CODES_FULL.BAKLAVA_1) {
-                containerView.requestRectangleOnScreen(
-                        caretPix,
-                        /* immediate= */ false,
-                        View.RECTANGLE_ON_SCREEN_REQUEST_SOURCE_TEXT_CURSOR);
-            } else {
-                // Fallback to previous API (where `requestRectangleOnScreen()` calls are assumed
-                // to come from text cursor moves).
-                containerView.requestRectangleOnScreen(caretPix);
+            if (caretPix != null) {
+                // Note: `SDK_INT_FULL` added in `BAKLAVA`, hence two checks.
+                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA
+                        && Build.VERSION.SDK_INT_FULL >= Build.VERSION_CODES_FULL.BAKLAVA_1) {
+                    containerView.requestRectangleOnScreen(
+                            caretPix,
+                            /* immediate= */ false,
+                            View.RECTANGLE_ON_SCREEN_REQUEST_SOURCE_TEXT_CURSOR);
+                } else {
+                    // Fallback to previous API (where `requestRectangleOnScreen()` calls are
+                    // assumed to come from text cursor moves).
+                    containerView.requestRectangleOnScreen(caretPix);
+                }
             }
         }
     }
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.