Chrome · Passwords
CVE-2026-87583
Logic Error in Passwords
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
TEST_Fchrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate_unittest.cc |
modified | |
GURLchrome/browser/webauthn/touch_to_fill_credential_receiver.h |
modified |
Files Changed
chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_credential_delegate.ccchrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_credential_delegate.hchrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_delegate.hchrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate.ccchrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate.hchrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate_unittest.ccchrome/browser/webauthn/android/webauthn_request_delegate_android.ccchrome/browser/webauthn/android/webauthn_request_delegate_android.hchrome/browser/webauthn/touch_to_fill_credential_receiver.h
Patch
From 49e2dbf4709abf6b1de30e5a27bcdac76e872bec Mon Sep 17 00:00:00 2001 From: Friedrich Horschig <[email protected]> Date: Tue, 28 Jul 2026 06:46:55 -0700 Subject: [PATCH] [Android][WebAuthn] Fix frame origin retrieval in TTF Delegate Prior to this CL, the origin of the parent frame would always be used when the "No Passkeys bottom sheet" shows up for a request originating from a subframe. This CL fixes the display issue and the const correctness of the getter. Fixed: 533116484 Change-Id: Ib1ecba0e949754d487637c30e8aae0a430212c02 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8163621 Reviewed-by: Adem Derinel <[email protected]> Commit-Queue: Friedrich Hauser <[email protected]> Cr-Commit-Position: refs/heads/main@{#1669428} --- diff --git a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_credential_delegate.cc b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_credential_delegate.cc index 1e874b6..7cc957d4 100644 --- a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_credential_delegate.cc +++ b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_credential_delegate.cc @@ -228,12 +228,13 @@ std::move(action_completed).Run(); } -GURL TouchToFillPasswordManagerCredentialDelegate::GetFrameUrl() { +GURL TouchToFillPasswordManagerCredentialDelegate::GetFrameUrl() const { CHECK(filler_); return filler_->GetFrameUrl(); } -url::Origin TouchToFillPasswordManagerCredentialDelegate::GetFrameOrigin() { +url::Origin TouchToFillPasswordManagerCredentialDelegate::GetFrameOrigin() + const { CHECK(filler_); return filler_->GetFrameOrigin(); } diff --git a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_credential_delegate.h b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_credential_delegate.h index c820880..245a2af3 100644 --- a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_credential_delegate.h +++ b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_credential_delegate.h @@ -126,8 +126,8 @@ void OnHybridSignInSelected(base::OnceClosure action_completed) override; void OnDismiss(base::OnceClosure action_completed) override; void OnCredManDismissed(base::OnceClosure action_completed) override; - GURL GetFrameUrl() override; - url::Origin GetFrameOrigin() override; + GURL GetFrameUrl() const override; + url::Origin GetFrameOrigin() const override; bool ShouldShowTouchToFill() override; bool ShouldTriggerSubmission() override; bool ShouldShowHybridOption() override; diff --git a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_delegate.h b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_delegate.h index 7aff6db..11fd5cc 100644 --- a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_delegate.h +++ b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_delegate.h @@ -64,11 +64,11 @@ // Gets the last committed URL for the frame that triggered this sheet to be // created. - virtual GURL GetFrameUrl() = 0; + virtual GURL GetFrameUrl() const = 0; // Gets the last committed origin for the frame that triggered this sheet to // be created. - virtual url::Origin GetFrameOrigin() = 0; + virtual url::Origin GetFrameOrigin() const = 0; // Returns whether TTF is eligible for showing for the currently focused field // (e. g. it should not be triggered for the new password field). diff --git a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate.cc b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate.cc index b40b068..ab61e7a 100644 --- a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate.cc +++ b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate.cc @@ -82,16 +82,13 @@ std::move(action_completed).Run(); } -GURL TouchToFillPasswordManagerWebAuthnDelegate::GetFrameUrl() { - return credential_receiver_->web_contents()->GetLastCommittedURL(); +GURL TouchToFillPasswordManagerWebAuthnDelegate::GetFrameUrl() const { + return credential_receiver_ ? credential_receiver_->GetFrameUrl() : GURL(); } -url::Origin TouchToFillPasswordManagerWebAuthnDelegate::GetFrameOrigin() { - return credential_receiver_->web_contents() - ? credential_receiver_->web_contents() - ->GetPrimaryMainFrame() - ->GetLastCommittedOrigin() - : url::Origin(); +url::Origin TouchToFillPasswordManagerWebAuthnDelegate::GetFrameOrigin() const { + return credential_receiver_ ? credential_receiver_->GetFrameOrigin() + : url::Origin(); } bool TouchToFillPasswordManagerWebAuthnDelegate::ShouldShowTouchToFill() { diff --git a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate.h b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate.h index 56b3cf1..39aada9 100644 --- a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate.h +++ b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate.h @@ -68,8 +68,8 @@ void OnHybridSignInSelected(base::OnceClosure action_completed) override; void OnDismiss(base::OnceClosure action_completed) override; void OnCredManDismissed(base::OnceClosure action_completed) override; - GURL GetFrameUrl() override; - url::Origin GetFrameOrigin() override; + GURL GetFrameUrl() const override; + url::Origin GetFrameOrigin() const override; bool ShouldShowTouchToFill() override; bool ShouldTriggerSubmission() override; bool ShouldShowHybridOption() override; diff --git a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate_unittest.cc b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate_unittest.cc index 02d1027..172a8cd 100644 --- a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate_unittest.cc +++ b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate_unittest.cc @@ -100,6 +100,14 @@ MOCK_METHOD(void, OnHybridSignInSelected, (), (override)); content::WebContents* web_contents() override { return web_contents_; } + GURL GetFrameUrl() const override { + return web_contents_ ? web_contents_->GetLastCommittedURL() : GURL(); + } + url::Origin GetFrameOrigin() const override { + return web_contents_ + ? web_contents_->GetPrimaryMainFrame()->GetLastCommittedOrigin() + : url::Origin(); + } private: raw_ptr<content::WebContents> web_contents_; @@ -373,3 +381,25 @@ std::vector<TouchToFillPasswordManagerView::Credential>, bool)>(webauthn::sorting::SortTouchToFillCredentials))); } + +TEST_F(TouchToFillPasswordManagerWebAuthnDelegateTest, GetFrameUrlAndOrigin) { + auto delegate = MakeTouchToFillPasswordManagerControllerDelegate( + /*should_show_hybrid_option=*/false, + /*is_immediate=*/true, + /*sorting_callback=*/base::NullCallback()); + + EXPECT_EQ(delegate->GetFrameUrl(), GURL(kExampleCom)); + EXPECT_EQ(delegate->GetFrameOrigin(), url::Origin::Create(GURL(kExampleCom))); +} + +TEST_F(TouchToFillPasswordManagerWebAuthnDelegateTest, + GetFrameUrlAndOriginNullReceiver) { + TouchToFillPasswordManagerWebAuthnDelegate delegate( + /*receiver=*/nullptr, + /*sort_credentials_callback=*/base::NullCallback(), + /*should_show_hybrid_option=*/false, + /*is_immediate=*/true); + + EXPECT_EQ(delegate.GetFrameUrl(), GURL()); + EXPECT_TRUE(delegate.GetFrameOrigin().opaque()); +} diff --git a/chrome/browser/webauthn/android/webauthn_request_delegate_android.cc b/chrome/browser/webauthn/android/webauthn_request_delegate_android.cc index cde7019e..c9ee628b 100644 --- a/chrome/browser/webauthn/android/webauthn_request_delegate_android.cc +++ b/chrome/browser/webauthn/android/webauthn_request_delegate_android.cc @@ -251,3 +251,11 @@ content::WebContents* WebAuthnRequestDelegateAndroid::web_contents() { return content::WebContents::FromRenderFrameHost(&render_frame_host()); } + +GURL WebAuthnRequestDelegateAndroid::GetFrameUrl() const { + return render_frame_host().GetLastCommittedURL(); +} + +url::Origin WebAuthnRequestDelegateAndroid::GetFrameOrigin() const { + return render_frame_host().GetLastCommittedOrigin(); +} diff --git a/chrome/browser/webauthn/android/webauthn_request_delegate_android.h b/chrome/browser/webauthn/android/webauthn_request_delegate_android.h index 0b067c6..ee9392d 100644 --- a/chrome/browser/webauthn/android/webauthn_request_delegate_android.h +++ b/chrome/browser/webauthn/android/webauthn_request_delegate_android.h @@ -80,6 +80,8 @@ void OnCredentialSelectionDeclined() override; void OnHybridSignInSelected() override; content::WebContents* web_contents() override; + GURL GetFrameUrl() const override; + url::Origin GetFrameOrigin() const override; // Returns a delegate associated with the |frame_host|. It creates one if // one does not already exist. diff --git a/chrome/browser/webauthn/touch_to_fill_credential_receiver.h b/chrome/browser/webauthn/touch_to_fill_credential_receiver.h index c963c31..4da9f8d1b 100644 --- a/chrome/browser/webauthn/touch_to_fill_credential_receiver.h +++ b/chrome/browser/webauthn/touch_to_fill_credential_receiver.h @@ -9,6 +9,9 @@ #include <vector> #include "chrome/browser/webauthn/shared_types.h" +#include "url/origin.h" + +class GURL; namespace content {
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate_unittest.cc b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate_unittest.cc
index 02d1027..172a8cd 100644
--- a/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate_unittest.cc
+++ b/chrome/browser/touch_to_fill/password_manager/touch_to_fill_password_manager_webauthn_delegate_unittest.cc
@@ -100,6 +100,14 @@
MOCK_METHOD(void, OnHybridSignInSelected, (), (override));
content::WebContents* web_contents() override { return web_contents_; }
+ GURL GetFrameUrl() const override {
+ return web_contents_ ? web_contents_->GetLastCommittedURL() : GURL();
+ }
+ url::Origin GetFrameOrigin() const override {
+ return web_contents_
+ ? web_contents_->GetPrimaryMainFrame()->GetLastCommittedOrigin()
+ : url::Origin();
+ }
private:
raw_ptr<content::WebContents> web_contents_;
@@ -373,3 +381,25 @@
std::vector<TouchToFillPasswordManagerView::Credential>,
bool)>(webauthn::sorting::SortTouchToFillCredentials)));
}
+
+TEST_F(TouchToFillPasswordManagerWebAuthnDelegateTest, GetFrameUrlAndOrigin) {
+ auto delegate = MakeTouchToFillPasswordManagerControllerDelegate(
+ /*should_show_hybrid_option=*/false,
+ /*is_immediate=*/true,
+ /*sorting_callback=*/base::NullCallback());
+
+ EXPECT_EQ(delegate->GetFrameUrl(), GURL(kExampleCom));
+ EXPECT_EQ(delegate->GetFrameOrigin(), url::Origin::Create(GURL(kExampleCom)));
+}
+
+TEST_F(TouchToFillPasswordManagerWebAuthnDelegateTest,
+ GetFrameUrlAndOriginNullReceiver) {
+ TouchToFillPasswordManagerWebAuthnDelegate delegate(
+ /*receiver=*/nullptr,
+ /*sort_credentials_callback=*/base::NullCallback(),
+ /*should_show_hybrid_option=*/false,
+ /*is_immediate=*/true);
+
+ EXPECT_EQ(delegate.GetFrameUrl(), GURL());
+ EXPECT_TRUE(delegate.GetFrameOrigin().opaque());
+}
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.
References
On This Page