Medium chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInappropriate implementation in Autofill
DescriptionInappropriate implementation in Autofill
ComponentAutofill
Bug ClassLogic Error
Tracker463551850
Fix commit69e11c8af383 (chromium/src) +99/-25
CISA KEVNot listed
CreditedManojkumar Jaganathan Aka TheWhiteEvil with HackerBro Technologies
Disclosed2026-07-29

Changed Functions

FunctionChangeNotes
BindRepeating
chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller_impl.cc
modified

Files Changed

  • chrome/browser/touch_to_fill/autofill/android/BUILD.gn
  • chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.cc
  • chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.h
  • chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller_impl.cc
From 69e11c8af383a4e30ff3af85fccc7b1a9a73caab Mon Sep 17 00:00:00 2001
From: Christoph Schwering <schwering@google.com>
Date: Tue, 09 Jun 2026 05:23:31 -0700
Subject: [PATCH] [Autofill] Migrate TTFPMControllerImpl to AutofillPopupHideHelper

This CL replaces TouchToFillPaymentMethodControllerImpl's custom
code that closes TTF on navigations and RFH destructions.

This brings along small behaviour changes that make it consistent
with other controllers: check for pointer lock, ancestor-check between
the focused frame and the form's frame, visibility tests.

Bug: 463551850
Change-Id: I0fcd955e7bbd4579698adaf9645a79f3d9206c1c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7909061
Reviewed-by: Jan Keitel <jkeitel@google.com>
Commit-Queue: Christoph Schwering <schwering@google.com>
Cr-Commit-Position: refs/heads/main@{#1643877}
---

diff --git a/chrome/browser/touch_to_fill/autofill/android/BUILD.gn b/chrome/browser/touch_to_fill/autofill/android/BUILD.gn
index c8a1102..38850beb 100644
--- a/chrome/browser/touch_to_fill/autofill/android/BUILD.gn
+++ b/chrome/browser/touch_to_fill/autofill/android/BUILD.gn
@@ -56,6 +56,7 @@
     "//base",
     "//chrome/android:chrome_jni_headers",
     "//chrome/browser/android:resource_mapper",
+    "//chrome/browser/ui/autofill",
     "//chrome/browser/ui/autofill/payments",
     "//components/affiliations/core/browser:affiliations",
     "//components/autofill/android:keyboard_suppressor",
diff --git a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.cc b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.cc
index 03b6be3..4102487 100644
--- a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.cc
+++ b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.cc
@@ -131,6 +131,10 @@
   HideTouchToFill();
 }
 
+BrowserAutofillManager& TouchToFillDelegateAndroidImpl::GetAutofillManager() {
+  return *manager_;
+}
+
 TouchToFillDelegateAndroidImpl::DryRunResult
 TouchToFillDelegateAndroidImpl::DryRun(FormGlobalId form_id,
                                        FieldGlobalId field_id) {
diff --git a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.h b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.h
index 64502ef..f69927b 100644
--- a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.h
+++ b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.h
@@ -107,6 +107,8 @@
       const TouchToFillDelegateAndroidImpl&) = delete;
   ~TouchToFillDelegateAndroidImpl() override;
 
+  BrowserAutofillManager& GetAutofillManager() override;
+
   // Checks whether TTF is eligible for the given web form data.
   // Only if this is true, the controller will show the view.
   bool IntendsToShowTouchToFill(FormGlobalId form_id,
diff --git a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller_impl.cc b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller_impl.cc
index 842aac7..4ea1d75 100644
--- a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller_impl.cc
+++ b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller_impl.cc
@@ -12,10 +12,12 @@
 #include "base/android/jni_string.h"
 #include "base/containers/span.h"
 #include "base/functional/callback.h"
+#include "base/functional/callback_helpers.h"
 #include "base/strings/strcat.h"
 #include "chrome/browser/android/resource_mapper.h"
 #include "chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.h"
 #include "chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_view.h"
+#include "chrome/browser/ui/autofill/autofill_suggestion_controller_utils.h"
 #include "chrome/browser/ui/autofill/payments/android_bnpl_ui_delegate.h"
 #include "components/autofill/content/browser/content_autofill_client.h"
 #include "components/autofill/content/browser/content_autofill_driver.h"
@@ -29,6 +31,7 @@
 #include "components/autofill/core/browser/payments/payments_util.h"
 #include "components/autofill/core/browser/suggestions/suggestion.h"
 #include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/web_contents.h"
 #include "ui/android/window_android.h"
 
 // Must come after all headers that specialize FromJniType() / ToJniType().
@@ -46,8 +49,7 @@
 
 TouchToFillPaymentMethodControllerImpl::TouchToFillPaymentMethodControllerImpl(
     ContentAutofillClient* autofill_client)
-    : content::WebContentsObserver(&autofill_client->GetWebContents()),
-      keyboard_suppressor_(
+    : keyboard_suppressor_(
           autofill_client,
           base::BindRepeating([](AutofillManager& manager) {
             return GetDelegate(manager) &&
@@ -70,6 +72,55 @@
   ResetJavaObject();
 }
 
+content::WebContents* TouchToFillPaymentMethodControllerImpl::web_contents() {
+  return driver_factory_observation_.GetSource()->web_contents();
+}
+
+bool TouchToFillPaymentMethodControllerImpl::InitHideHelper(
+    TouchToFillDelegate& delegate) {
+  // The focused frame may be a different frame than the one the delegate is
+  // associated with. This happens in two scenarios:
+  // - With frame-transcending forms: the focused frame is subframe, whose
+  //   form has been flattened into an ancestor form.
+  // - With race conditions: while Autofill parsed the form, the focus may
+  //   have moved to another frame.
+  // We support the case where the focused frame is a descendant of the
+  // `delegate_`'s frame. We observe the focused frame's RenderFrameDeleted()
+  // event.
+  content::RenderFrameHost* rfh = web_contents()->GetFocusedFrame();
+  content::RenderFrameHost* delegate_rfh =
+      static_cast<ContentAutofillDriver&>(
+          delegate.GetAutofillManager().driver())
+          .render_frame_host();
+
+  if (!rfh || !IsAncestorOf(delegate_rfh, rfh)) {
+    return false;
+  }
+
+  if (IsPointerLocked(web_contents())) {
+    return false;
+  }
+
+  // The bottom sheet steals the focus from the WebContents, so we cannot rely
+  // on AutofillPopupHideHelper's focus handling.
+  AutofillPopupHideHelper::HidingParams params = {
+      .hide_on_web_contents_lost_focus = false};
+
+  AutofillPopupHideHelper::HidingCallback hide_callback =
+      base::IgnoreArgs<SuggestionHidingReason>(
+          base::BindRepeating(&TouchToFillPaymentMethodControllerImpl::Hide,
+                              base::Unretained(this)));
+
+  // TODO(crbug.com/521318493): Should we hide TTF in the face of a PiP?
+  AutofillPopupHideHelper::PictureInPictureDetectionCallback
+      pip_detection_callback = base::BindRepeating([]() { return false; });
+
+  hide_helper_.emplace(web_contents(), rfh->GetGlobalId(), std::move(params),
+                       std::move(hide_callback),
+                       std::move(pip_detection_callback));
+  return true;
+}
+
 bool TouchToFillPaymentMethodControllerImpl::ShowPaymentMethods(
     std::unique_ptr<TouchToFillPaymentMethodView> view,
     base::WeakPtr<TouchToFillDelegate> delegate,
@@ -83,6 +134,10 @@
     return false;
   }
 
+  if (!InitHideHelper(*delegate)) {
+    return false;
+  }
+
   if (!view->ShowPaymentMethods(
           this, suggestions,
           payments::TouchToFillDisplayOptions{
@@ -110,6 +165,10 @@
     return false;
   }
 
+  if (!InitHideHelper(*delegate)) {
+    return false;
+  }
+
   if (!view->ShowIbans(this, ibans_to_suggest)) {
     ResetJavaObject();
     return false;
@@ -126,7 +185,7 @@
     base::span<const LoyaltyCard> affiliated_loyalty_cards,
     base::span<const LoyaltyCard> all_loyalty_cards,
     bool first_time_usage) {
-  // TODO(crbug.com/404437211): Unify `ShowX()` methods to avoid code
+  // TODO(crbug.com/521032396): Unify `ShowX()` methods to avoid code
   // duplication.
   if (!keyboard_suppressor_.is_suppressing()) {
     return false;
@@ -137,6 +196,10 @@
     return false;
   }
 
+  if (!InitHideHelper(*delegate)) {
+    return false;
+  }
+
   if (!view->ShowAffiliatedLoyaltyCards(this, affiliated_loyalty_cards,
                                         all_loyalty_cards, first_time_usage)) {
     ResetJavaObject();
@@ -157,6 +220,10 @@
     return false;
   }
 
+  if (!InitHideHelper(*delegate)) {
+    return false;
+  }
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller_impl_unittest.cc b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller_impl_unittest.cc
index bdc0245..100fb31 100644
--- a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller_impl_unittest.cc
+++ b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller_impl_unittest.cc
@@ -192,6 +192,8 @@
   void SetUp() override {
     ChromeRenderViewHostTestHarness::SetUp();
     NavigateAndCommit(GURL("about:blank"));
+    FocusWebContentsOnMainFrame();
+    ASSERT_TRUE(web_contents()->GetFocusedFrame());
     autofill_manager().set_touch_to_fill_delegate(
         std::make_unique<MockTouchToFillDelegateAndroidImpl>(
             &autofill_manager()));
diff --git a/components/autofill/core/browser/foundations/browser_autofill_manager_unittest.cc b/components/autofill/core/browser/foundations/browser_autofill_manager_unittest.cc
index bd7f1db..247f5067 100644
--- a/components/autofill/core/browser/foundations/browser_autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/foundations/browser_autofill_manager_unittest.cc
@@ -204,6 +204,7 @@
 using ::testing::Property;
 using ::testing::Ref;
 using ::testing::Return;
+using ::testing::ReturnRef;
 using ::testing::SaveArg;
 using ::testing::UnorderedElementsAre;
 using ::testing::VariantWith;
@@ -632,6 +633,7 @@
   static std::unique_ptr<MockTouchToFillDelegate> Create(
       BrowserAutofillManager* manager) {
     auto delegate = std::make_unique<NiceMock<MockTouchToFillDelegate>>();
+    ON_CALL(*delegate, GetAutofillManager()).WillByDefault(ReturnRef(*manager));
     ON_CALL(*delegate, IsShowingTouchToFill()).WillByDefault(Return(false));
     return delegate;
   }
@@ -641,6 +643,7 @@
   MockTouchToFillDelegate& operator=(const MockTouchToFillDelegate&) = delete;
   ~MockTouchToFillDelegate() override = default;
 
+  MOCK_METHOD(BrowserAutofillManager&, GetAutofillManager, (), (override));
   MOCK_METHOD(bool,
               IntendsToShowTouchToFill,
               (FormGlobalId, FieldGlobalId),
Loading diff…

Original Bug Report

reported by bu...@gmail.com

Debit/Credit Card Autofill Leakage via Cross-Origin Rendering in Chrome 142.0.7444.171 for Android

Steps to reproduce the problem

  1. Visit https://attacker.hackerbro.net/exploit.html in Chrome for Android.
  2. Tap the Credit Card option and then tap Verify Info.
  3. The page redirects to https://splendorous-truffle-da6efb.netlify.app/card.html (a different origin).
  4. After the redirect, Chrome shows the stored card prompt on this cross-origin page.
  5. When the user clicks OK to populate the stored card, the card details are not filled into the currently visible page.
  6. Instead, Chrome autofills the stored card information into the attacker-controlled origin, resulting in cross-origin autofill leakage.

Problem Description

  • In Chrome version 142.0.7444.171, stored debit and credit cards are being rendered across origins. This cross-origin rendering exposes sensitive autofill data, allowing leakage when the card prompt is triggered on an external domain.

Impact:

  • Potential exposure of users’ payment card information to malicious websites via autofill.

Recommendation:

  • Restrict cross-origin access to stored payment methods and enforce same-origin policies for autofill prompts.

Summary

Debit/Credit Card Autofill Leakage via Cross-Origin Rendering in Chrome 142.0.7444.171 for Android

Custom Questions

Reporter credit:

Manojkumar Jaganathan (https://www.linkedin.com/in/manojkumar-j-7ba35b202/) Aka TheWhiteEvil (https://hackerone.com/the-white-evil) with HackerBro Technologies

Additional Data

Category: Security
Chrome Channel: Stable
Regression: No \

View on issue tracker