Medium chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactIncorrect security UI in Passwords
DescriptionIncorrect security UI in Passwords
ComponentPasswords
Bug ClassLogic Error
Tracker514006829
Fix commit2749edae91e0 (chromium/src) +37/-19
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-30

Changed Functions

FunctionChangeNotes
PopupBaseView modified
if
chrome/browser/ui/views/autofill/popup/popup_base_view.cc
modified

Files Changed

  • chrome/browser/ui/views/autofill/popup/popup_base_view.cc
  • chrome/browser/ui/views/autofill/popup/popup_base_view.h
  • chrome/browser/ui/views/autofill/popup/popup_view_views.cc
From 2749edae91e090b735b9ae8b65a52476409cfd18 Mon Sep 17 00:00:00 2001
From: Mohamed Amir Yosef <mamir@chromium.org>
Date: Tue, 19 May 2026 05:22:10 -0700
Subject: [PATCH] [Autofill]: Hoist overlap checks into PopupBaseView

Hoist open prompt, permission bubble, and HTML form popup overlap checks
from PopupViewViews into the base class PopupBaseView.

Previously, the sibling class PopupViewViews implemented overlap checks
for open prompts, permission dialogs, and HTML form popups to prevent
clickjacking attacks. However, password-related popup views (such as
PasswordGenerationPopupViewViews and
PasswordCrossDomainConfirmationPopupViewViews) inherit from the base
class PopupBaseView and did not inherit these checks. A compromised
renderer could therefore position a password-related popup to obscure
trusted browser dialogs.

This CL hoists these checks into a shared helper method
HideIfOverlappingWithAnotherPrompt in PopupBaseView and calls it in both
PopupBaseView and PopupViewViews to protect all popup subclasses while
avoiding duplicate code.

Fixed: 514006829
Test: out/Default/unit_tests --gtest_filter="PopupBaseViewBrowsertest.*:PopupViewViewsTest.*"
Change-Id: I7239b3e643c1b4dbe3defab22c7cdef51a5789d3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7853421
Reviewed-by: Dominic Battré <battre@chromium.org>
Commit-Queue: Mohamed Amir Yosef <mamir@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1632784}
---

diff --git a/chrome/browser/ui/views/autofill/popup/popup_base_view.cc b/chrome/browser/ui/views/autofill/popup/popup_base_view.cc
index 5efd1fde..5c9c09d1 100644
--- a/chrome/browser/ui/views/autofill/popup/popup_base_view.cc
+++ b/chrome/browser/ui/views/autofill/popup/popup_base_view.cc
@@ -577,6 +577,11 @@
       element_bounds, visible_content_area_bounds, preferred_size,
       kDefaultPreferredPopupSides);
 
+  if (OverlapsWithAnotherPrompt(popup_bounds)) {
+    HideController(SuggestionHidingReason::kOverlappingWithAnotherPrompt);
+    return false;
+  }
+
   if (BoundsOverlapWithPictureInPictureWindow(popup_bounds)) {
     HideController(
         SuggestionHidingReason::kOverlappingWithPictureInPictureWindow);
@@ -593,6 +598,33 @@
   return true;
 }
 
+bool PopupBaseView::OverlapsWithAnotherPrompt(
+    const gfx::Rect& popup_bounds) const {
+  content::WebContents* web_contents = GetWebContents();
+  if (!web_contents) {
+    return false;
+  }
+
+  if (BoundsOverlapWithAnyOpenPrompt(popup_bounds, web_contents)) {
+    return true;
+  }
+  // On Windows, due to platform-specific implementation details, the previous
+  // check isn't reliable, and fails to detect open prompts. Since the most
+  // critical bubble is the permission bubble, we check for that specifically.
+  if (BoundsOverlapWithOpenPermissionsPrompt(popup_bounds, web_contents)) {
+    return true;
+  }
+
+  if (base::FeatureList::IsEnabled(
+          features::kAutofillPopupCheckHtmlFormPopupOverlap)) {
+    if (BoundsOverlapWithHtmlFormPopup(popup_bounds, web_contents)) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 void PopupBaseView::OnNativeFocusChanged(gfx::NativeView focused_now) {
   // TODO(crbug.com/330303918): The focus change is triggered sometimes
   // (reproduced on a Linux release build, on a debug one - no) with
diff --git a/chrome/browser/ui/views/autofill/popup/popup_base_view.h b/chrome/browser/ui/views/autofill/popup/popup_base_view.h
index ba14966..dac026d 100644
--- a/chrome/browser/ui/views/autofill/popup/popup_base_view.h
+++ b/chrome/browser/ui/views/autofill/popup/popup_base_view.h
@@ -93,6 +93,10 @@
   // testing).
   [[nodiscard]] virtual bool DoUpdateBoundsAndRedrawPopup();
 
+  // Checks whether the popup at `popup_bounds` overlaps with any open prompts,
+  // permission bubbles, or HTML form popups.
+  bool OverlapsWithAnotherPrompt(const gfx::Rect& popup_bounds) const;
+
   // Returns the optimal bounds to place the popup with `preferred_size` and
   // places an arrow on the popup border to point towards `element_bounds`
   // within `max_bounds_for_popup`. The `preferred_popup_sides` are tried
diff --git a/chrome/browser/ui/views/autofill/popup/popup_view_views.cc b/chrome/browser/ui/views/autofill/popup/popup_view_views.cc
index 3deaf6fa..3fdbf1e9 100644
--- a/chrome/browser/ui/views/autofill/popup/popup_view_views.cc
+++ b/chrome/browser/ui/views/autofill/popup/popup_view_views.cc
@@ -1518,28 +1518,10 @@
       element_bounds, visible_content_area_bounds, preferred_size,
       preferred_popup_sides);
 
-  if (BoundsOverlapWithAnyOpenPrompt(popup_bounds,
-                                     controller_->GetWebContents())) {
+  if (OverlapsWithAnotherPrompt(popup_bounds)) {
     controller_->Hide(SuggestionHidingReason::kOverlappingWithAnotherPrompt);
     return false;
   }
-  // On Windows, due to platform-specific implementation details, the previous
-  // check isn't reliable, and fails to detect open prompts. Since the most
-  // critical bubble is the permission bubble, we check for that specifically.
-  if (BoundsOverlapWithOpenPermissionsPrompt(popup_bounds,
-                                             controller_->GetWebContents())) {
-    controller_->Hide(SuggestionHidingReason::kOverlappingWithAnotherPrompt);
-    return false;
-  }
-
-  if (base::FeatureList::IsEnabled(
-          features::kAutofillPopupCheckHtmlFormPopupOverlap)) {
-    if (BoundsOverlapWithHtmlFormPopup(popup_bounds,
-                                       controller_->GetWebContents())) {
-      controller_->Hide(SuggestionHidingReason::kOverlappingWithAnotherPrompt);
-      return false;
-    }
-  }
 
   // The pip surface is given the most preference while rendering. So, the
   // autofill popup should not be shown when the picture in picture window
Loading diff…

Original Bug Report

reported by vm...@google.com

UI obscuration and clickjacking in Password Generation Popup via PopupBaseView

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: PopupBaseView lacks overlap checks for permission prompts and other browser dialogs, unlike PopupViewViews. A compromised renderer can exploit this to position password-related popups over sensitive UI elements. This may facilitate clickjacking attacks where users accidentally grant browser permissions.

Affected files:

  • chrome/browser/ui/views/autofill/popup/popup_base_view.cc
  • chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc
  • chrome/browser/ui/views/passwords/password_cross_domain_confirmation_popup_view_views.cc

Estimated timestamp from git blame: 2024-04-25

Potential Vulnerability Description

A potential security issue has been identified in autofill::PopupBaseView, which is the base class for various password-related and autofill popups in Chromium. The method PopupBaseView::DoUpdateBoundsAndRedrawPopup() is responsible for positioning and rendering these popups. While it includes a check for overlaps with Picture-in-Picture windows, it lacks several security-critical overlap checks found in its sibling implementation, PopupViewViews (used for standard Autofill suggestions).

Specifically, PopupBaseView is missing calls to BoundsOverlapWithAnyOpenPrompt(), BoundsOverlapWithOpenPermissionsPrompt(), and BoundsOverlapWithHtmlFormPopup(). These checks are designed to hide the popup if it would otherwise obscure a security-sensitive browser prompt or dialog.

Technical Details

Popups inheriting from PopupBaseView, including PasswordGenerationPopupViewViews and PasswordCrossDomainConfirmationPopupViewViews, are created with ui::ZOrderLevel::kSecuritySurface (when the kAutofillPopupZOrderSecuritySurface feature is enabled). This Z-order level is higher than the default kNormal level used by browser permission bubbles. Consequently, these popups can render on top of and obscure permission dialogs.

Since a compromised renderer can influence the bounds of these popups via Mojo interfaces (e.g., mojom::PasswordGenerationDriver::ShowPasswordEditingPopup), it can potentially position them to cover critical context in a permission prompt, such as the site origin or the ‘Block’ button. This creates a clickjacking risk where a user, intending to interact with the trusted password manager UI, may accidentally click the ‘Allow’ button on an underlying permission prompt.

Potential Attack Scenario

  1. Renderer Compromise: An attacker compromises a renderer process through a separate vulnerability.
  2. Trigger Permission: The renderer triggers a browser permission prompt (e.g., for camera or geolocation).
  3. Position Popup: The compromised renderer calls ShowPasswordEditingPopup via the PasswordGenerationDriver interface, supplying specific bounds designed to overlap the permission bubble.
  4. Obscure Context: The browser displays the password generation popup at the specified location. Because PopupBaseView lacks overlap checks, it does not detect the collision with the permission bubble.
  5. Clickjacking: The user is tricked into clicking an exposed ‘Allow’ button on the permission prompt, which the attacker has rendered partially visible while obscuring the origin label.

Note: These are potential steps based on source code analysis; functional proof-of-concept testing has not been performed.

Affected Files

  • chrome/browser/ui/views/autofill/popup/popup_base_view.cc
  • chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc
  • chrome/browser/ui/views/passwords/password_cross_domain_confirmation_popup_view_views.cc

Recommendation

The overlap checks (BoundsOverlapWithAnyOpenPrompt, BoundsOverlapWithOpenPermissionsPrompt, and BoundsOverlapWithHtmlFormPopup) should be hoisted from PopupViewViews::DoUpdateBoundsAndRedrawPopup() into the base class PopupBaseView::DoUpdateBoundsAndRedrawPopup(). This ensures that all subclasses correctly handle potential collisions with security-sensitive UI elements.

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