Medium chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInsufficient validation of untrusted input in Mobile
DescriptionInsufficient validation of untrusted input in Mobile
ComponentMobile
Bug ClassLogic Error
Tracker514067070
Fix commit0a5df90c851f (chromium/src) +20/-2
CISA KEVNot listed
CreditedGoogle
Disclosed2026-07-29

Files Changed

  • cc/mojom/render_frame_metadata_mojom_traits.cc
  • chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java
From 0a5df90c851f96937359903f9cfe16c734fe64de Mon Sep 17 00:00:00 2001
From: Mark Schillaci <[email protected]>
Date: Thu, 04 Jun 2026 16:33:42 -0700
Subject: [PATCH] Clamp top and bottom control offsets to be on screen

This CL updates the deserialization traits for RenderFrameMetadata to
verify that the top and bottom control heights are finite and
non-negative. Unexpected values could cause the browser to render the
controls incorrectly or offscreen. By clamping the values, we can ensure
that the top controls are always visible.

Bug: 514067070
Change-Id: Ic173324baf0f364c10cac0d484cc19a587056ad7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7868572
Reviewed-by: Tom Sepez <[email protected]>
Reviewed-by: Wenyu Fu <[email protected]>
Commit-Queue: Mark Schillaci <[email protected]>
Reviewed-by: Sinan Sahin <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1642022}
---

diff --git a/cc/mojom/render_frame_metadata_mojom_traits.cc b/cc/mojom/render_frame_metadata_mojom_traits.cc
index 8d22520..10b28ad 100644
--- a/cc/mojom/render_frame_metadata_mojom_traits.cc
+++ b/cc/mojom/render_frame_metadata_mojom_traits.cc
@@ -35,11 +35,29 @@
   out->external_page_scale_factor = data.external_page_scale_factor();
   out->top_controls_height = data.top_controls_height();
   out->top_controls_shown_ratio = data.top_controls_shown_ratio();
+
+  // Ensure top controls are finite and non-negative heights so that the top
+  // controls cannot be moved offscreen by the renderer.
+  if (!std::isfinite(out->top_controls_height) ||
+      out->top_controls_height < 0 ||
+      !std::isfinite(out->top_controls_shown_ratio)) {
+    return false;
+  }
+
   out->primary_main_frame_item_sequence_number =
       data.primary_main_frame_item_sequence_number();
 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
   out->bottom_controls_height = data.bottom_controls_height();
   out->bottom_controls_shown_ratio = data.bottom_controls_shown_ratio();
+
+  // Ensure bottom controls are finite and non-negative heights so that the
+  // bottom controls cannot be moved offscreen by the renderer.
+  if (!std::isfinite(out->bottom_controls_height) ||
+      out->bottom_controls_height < 0 ||
+      !std::isfinite(out->bottom_controls_shown_ratio)) {
+    return false;
+  }
+
   out->top_controls_min_height_offset = data.top_controls_min_height_offset();
   out->bottom_controls_min_height_offset =
       data.bottom_controls_min_height_offset();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java
index fe3af42..ad042469 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java
@@ -625,8 +625,8 @@
 
         // Make the bottom controls height smaller by the shadow height so that
         // the shadow is displayed over the bottom of the WebContents.
-        mBrowserControlsSizer.setBottomControlsHeight(
-                minHeight + height - mShadowHeightPx, minHeight);
+        int bottomControlsHeight = Math.max(0, height - mShadowHeightPx);
+        mBrowserControlsSizer.setBottomControlsHeight(minHeight + bottomControlsHeight, minHeight);
     }
 
     // SwipeGestureListener.SwipeHandler methods
Loading diff…

Original Bug Report

reported by [email protected]

Potential URL bar spoofing on Android via unvalidated top-controls metadata

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 potential URL bar spoofing vulnerability exists in Chrome for Android where a compromised renderer can move the authoritative browser UI off-screen. This is due to a lack of range validation for top-controls metadata in the browser process. An attacker can use this to hide the real URL bar and paint a fake origin in the web content.

Affected files:

  • chrome/android/java/src/org/chromium/chrome/browser/fullscreen/BrowserControlsManager.java
  • content/browser/renderer_host/render_widget_host_view_android.cc
  • cc/mojom/render_frame_metadata_mojom_traits.cc
  • chrome/browser/browser_controls/android/java/src/org/chromium/chrome/browser/browser_controls/TopControlsStacker.java
  • chrome/browser/android/compositor/layer/toolbar_layer.cc
  • chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/StaticLayout.java
  • chrome/browser/android/compositor/scene_layer/static_tab_scene_layer.cc

Estimated timestamp from git blame: 2018-05-15

Summary

A compromised renderer process can potentially perform a complete URL bar and origin spoof on Chrome for Android. By providing crafted cc::mojom::RenderFrameMetadata values, an attacker can displace the security-critical browser-rendered URL bar off-screen while positioning malicious web content in its place. This is possible because the browser process does not adequately validate the range or sanity of renderer-supplied control offsets.

Vulnerability Details

The vulnerability exists in the handling of top-controls metadata sent from the renderer to the browser:

  1. Missing Mojo Validation: In cc/mojom/render_frame_metadata_mojom_traits.cc, the top_controls_height and top_controls_shown_ratio fields are deserialized as raw floats without range checks. A compromised renderer can provide extreme or negative values.

  2. Malformed Offset Calculation (C++): In content/browser/renderer_host/render_widget_host_view_android.cc, the browser calculates a translation offset (top_translate) using the formula: top_translate = (top_controls_height * top_controls_shown_ratio) - top_controls_height. By supplying a large negative height (e.g., -10000.0) and a zero ratio, a renderer triggers a large positive offset (+10000.0).

  3. Incomplete Clamping (Java): This malformed offset is passed via JNI to BrowserControlsManager.java. In the setPositionsForTab method, the code applies a lower-bound clamp (Math.max(topControlsOffset, -getTopControlsHeight())) to prevent the controls from moving too far up, but it fails to apply an upper-bound clamp. Consequently, the large positive offset (10000) persists.

  4. UI Displacement and Hiding: This offset causes the browser to translate the Android View-based toolbar 10000 pixels down (off-screen). Additionally, since the browser calculates a “hidden ratio” greater than zero, it may set the real toolbar view to INVISIBLE. Meanwhile, the web content is positioned at Y=0. The renderer can then fill the space where the omnibox should be with its own content, mimicking a legitimate browser UI.

Impact

This is a high-severity security boundary bypass. The browser-process-rendered URL bar is the authoritative source of truth for a site’s identity. If it can be hidden or replaced by web content, a compromised renderer can effectively spoof any origin (e.g., a login page for a financial institution) to the user.

Potential Reproduction Steps

  1. Gain control of a renderer process (precondition).
  2. Manually send a cc::mojom::RenderFrameMetadata Mojo message to the browser with top_controls_height = -10000.0f and top_controls_shown_ratio = 0.0f.
  3. Observe that the legitimate URL bar is shifted off-screen or disappears.
  4. The renderer can now paint a fake UI in the top area of the screen where the omnibox normally resides.

Suggested Fix

  1. Implement strict range validation in cc/mojom/render_frame_metadata_mojom_traits.cc. Ensure top_controls_height is non-negative and top_controls_shown_ratio is finite and within the [0, 1] range.
  2. Add an upper-bound clamp in BrowserControlsManager.java (e.g., Math.min(topControlsOffset, 0)) to ensure the controls cannot be moved downward beyond their resting position.

Evaluated with Chrome root at commit: 1a8d40fc44df2088d5945c0bf53584038aa1614a


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