Low chrome Logic Error 🔧 Commit mapped

Overview

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

Changed Functions

FunctionChangeNotes
if
ios/chrome/browser/passwords/bottom_sheet/coordinator/passkey_creation_bottom_sheet_mediator.mm
modified

Files Changed

  • components/webauthn/ios/passkey_tab_helper.h
  • components/webauthn/ios/passkey_tab_helper.mm
  • ios/chrome/browser/passwords/bottom_sheet/coordinator/passkey_creation_bottom_sheet_mediator.mm
  • ios/chrome/browser/passwords/bottom_sheet/ui/passkey_creation_bottom_sheet_consumer.h
  • ios/chrome/browser/passwords/bottom_sheet/ui/passkey_creation_bottom_sheet_view_controller.mm
  • ios/chrome/browser/passwords/bottom_sheet/ui/passkey_creation_bottom_sheet_view_controller_unittest.mm
From 2cbdf7e9709ac470e737a2e2919e05356e5c19c6 Mon Sep 17 00:00:00 2001
From: Rafał Godlewski <[email protected]>
Date: Fri, 29 May 2026 05:49:51 -0700
Subject: [PATCH] [iOS][WebAuthn] Use rp_id in passkey creation bottom sheet

Display the actual RP ID from the WebAuthn request in the passkey
creation bottom sheet, instead of using the top-level frame's last
committed URL, as it might differ for cross-origin subframes.

Fixed: 514075028
Change-Id: Ie890dd05dd522b7d297c1aefcd12475585312051
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7883325
Reviewed-by: Alexis Hétu <[email protected]>
Commit-Queue: Rafał Godlewski <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1638418}
---

diff --git a/components/webauthn/ios/passkey_tab_helper.h b/components/webauthn/ios/passkey_tab_helper.h
index 3b10c2f..57fa512d 100644
--- a/components/webauthn/ios/passkey_tab_helper.h
+++ b/components/webauthn/ios/passkey_tab_helper.h
@@ -111,6 +111,10 @@
   // have a username.
   std::string UsernameForRequest(const std::string& request_id);
 
+  // Returns the relying party identifier associated with the current request ID
+  // or an empty string if the request is not found.
+  std::string RelyingPartyIdForRequest(const std::string& request_id);
+
   // Sets the passkey command handler.
   void SetIOSPasskeyClientCommandsHandler(id<IOSPasskeyClientCommands> handler);
 
diff --git a/components/webauthn/ios/passkey_tab_helper.mm b/components/webauthn/ios/passkey_tab_helper.mm
index fc19c054..dcaaa1c 100644
--- a/components/webauthn/ios/passkey_tab_helper.mm
+++ b/components/webauthn/ios/passkey_tab_helper.mm
@@ -740,6 +740,23 @@
   return "";
 }
 
+std::string PasskeyTabHelper::RelyingPartyIdForRequest(
+    const std::string& request_id) {
+  // Check registration requests first.
+  auto registration_it = registration_requests_.find(request_id);
+  if (registration_it != registration_requests_.end()) {
+    return registration_it->second.RpId();
+  }
+
+  // Check assertion requests next.
+  auto assertion_it = assertion_requests_.find(request_id);
+  if (assertion_it != assertion_requests_.end()) {
+    return assertion_it->second.RpId();
+  }
+
+  return "";
+}
+
 std::optional<bool> PasskeyTabHelper::ShouldPerformUserVerification(
     const std::string& request_id,
     bool is_biometric_authentication_enabled) const {
diff --git a/ios/chrome/browser/passwords/bottom_sheet/coordinator/passkey_creation_bottom_sheet_mediator.mm b/ios/chrome/browser/passwords/bottom_sheet/coordinator/passkey_creation_bottom_sheet_mediator.mm
index 69394dde..76e689d7 100644
--- a/ios/chrome/browser/passwords/bottom_sheet/coordinator/passkey_creation_bottom_sheet_mediator.mm
+++ b/ios/chrome/browser/passwords/bottom_sheet/coordinator/passkey_creation_bottom_sheet_mediator.mm
@@ -42,9 +42,6 @@
 
   // Module containing the reauthentication mechanism.
   id<ReauthenticationProtocol> _reauthModule;
-
-  // URL of the current page the bottom sheet is being displayed on.
-  GURL _URL;
 }
 
 - (instancetype)
@@ -66,7 +63,6 @@
     _requestInfo = std::move(requestInfo);
     _accountForSaving = accountForSaving;
     _reauthModule = reauthModule;
-    _URL = webStateList->GetActiveWebState()->GetLastCommittedURL();
     _mediatorDelegate = mediatorDelegate;
   }
   return self;
@@ -176,8 +172,15 @@
 #pragma mark - Accessors
 
 - (void)setConsumer:(id<PasskeyCreationBottomSheetConsumer>)consumer {
+  NSString* rpId = [self rpId];
+  if (!rpId) {
+    // The RP ID should not be empty, dismiss the flow.
+    [_mediatorDelegate dismissPasskeyCreation];
+    return;
+  }
+
   _consumer = consumer;
-  [_consumer setUsername:[self username] email:[self email] url:_URL];
+  [_consumer setUsername:[self username] email:[self email] rpId:rpId];
 }
 
 #pragma mark - WebStateListObserving
@@ -198,6 +201,22 @@
 
 #pragma mark - Private
 
+// Returns the relying party identifier for the passkey request.
+- (NSString*)rpId {
+  webauthn::PasskeyTabHelper* passkeyTabHelper = [self passkeyTabHelper];
+  if (!passkeyTabHelper || !_requestInfo.has_value()) {
+    return nil;
+  }
+
+  std::string rpId =
+      passkeyTabHelper->RelyingPartyIdForRequest(_requestInfo->request_id);
+  if (rpId.empty()) {
+    return nil;
+  }
+
+  return base::SysUTF8ToNSString(rpId);
+}
+
 // Returns the username for the passkey request.
 - (NSString*)username {
   webauthn::PasskeyTabHelper* passkeyTabHelper = [self passkeyTabHelper];
diff --git a/ios/chrome/browser/passwords/bottom_sheet/ui/passkey_creation_bottom_sheet_consumer.h b/ios/chrome/browser/passwords/bottom_sheet/ui/passkey_creation_bottom_sheet_consumer.h
index 12b3e4a..7c1f4de 100644
--- a/ios/chrome/browser/passwords/bottom_sheet/ui/passkey_creation_bottom_sheet_consumer.h
+++ b/ios/chrome/browser/passwords/bottom_sheet/ui/passkey_creation_bottom_sheet_consumer.h
@@ -7,13 +7,14 @@
 
 #import <Foundation/Foundation.h>
 
-#import "url/gurl.h"
-
 // Delegate for the passkey creation bottom sheet.
 @protocol PasskeyCreationBottomSheetConsumer
 
-// Sets the username, email and url for the current passkey request.
-- (void)setUsername:(NSString*)username email:(NSString*)email url:(GURL)URL;
+// Sets the username, email and relying party identifier for the current passkey
+// request.
+- (void)setUsername:(NSString*)username
+              email:(NSString*)email
+               rpId:(NSString*)rpId;
 
 @end
 
diff --git a/ios/chrome/browser/passwords/bottom_sheet/ui/passkey_creation_bottom_sheet_view_controller.mm b/ios/chrome/browser/passwords/bottom_sheet/ui/passkey_creation_bottom_sheet_view_controller.mm
index 015f54e..331b9a2 100644
--- a/ios/chrome/browser/passwords/bottom_sheet/ui/passkey_creation_bottom_sheet_view_controller.mm
+++ b/ios/chrome/browser/passwords/bottom_sheet/ui/passkey_creation_bottom_sheet_view_controller.mm
@@ -160,8 +160,8 @@
   // The email for the passkey request.
   NSString* _email;
 
-  // URL of the current page the bottom sheet is being displayed on.
-  GURL _url;
+  // Relying party identifier of the passkey request.
+  NSString* _rpId;
 
   // The passkey creation handler for user actions.
   __weak id<BrowserCoordinatorCommands> _handler;
@@ -217,10 +217,12 @@
 
 #pragma mark - PasskeyCreationBottomSheetConsumer
 
-- (void)setUsername:(NSString*)username email:(NSString*)email url:(GURL)url {
+- (void)setUsername:(NSString*)username
+              email:(NSString*)email
+               rpId:(NSString*)rpId {
   _username = username;
   _email = email;
-  _url = url;
+  _rpId = rpId;
 }
 
 #pragma mark - Private
@@ -249,8 +251,9 @@
 
     faviconView.contentMode = UIViewContentModeScaleAspectFit;
     faviconView.tintColor = [UIColor colorNamed:kTextPrimaryColor];
+    GURL pageURL("https://" + base::SysNSStringToUTF8(_rpId));
     _faviconLoader->FaviconForPageUrl(
-        _url, kFaviconSize, kFaviconSize,
+        pageURL, kFaviconSize, kFaviconSize,
         /*fallback_to_google_server=*/true,
         ^(FaviconAttributes* attributes, bool cached) {
           [faviconView configureWithAttributes:attributes];
@@ -262,7 +265,7 @@
   usernameLabel.text = _username;
 
   UILabel* domainLabel = CreateDomainLabel();
-  domainLabel.text = base::SysUTF8ToNSString(_url.host());
+  domainLabel.text = _rpId;
 
   UIStackView* textStack =
       CreateLabelsStackView(@[ usernameLabel, domainLabel ]);
diff --git a/ios/chrome/browser/passwords/bottom_sheet/ui/passkey_creation_bottom_sheet_view_controller_unittest.mm b/ios/chrome/browser/passwords/bottom_sheet/ui/passkey_creation_bottom_sheet_view_controller_unittest.mm
index 3512a092..6331d17 100644
--- a/ios/chrome/browser/passwords/bottom_sheet/ui/passkey_creation_bottom_sheet_view_controller_unittest.mm
+++ b/ios/chrome/browser/passwords/bottom_sheet/ui/passkey_creation_bottom_sheet_view_controller_unittest.mm
@@ -21,7 +21,6 @@
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/ios/chrome/browser/passwords/bottom_sheet/ui/passkey_creation_bottom_sheet_view_controller_unittest.mm b/ios/chrome/browser/passwords/bottom_sheet/ui/passkey_creation_bottom_sheet_view_controller_unittest.mm
index 3512a092..6331d17 100644
--- a/ios/chrome/browser/passwords/bottom_sheet/ui/passkey_creation_bottom_sheet_view_controller_unittest.mm
+++ b/ios/chrome/browser/passwords/bottom_sheet/ui/passkey_creation_bottom_sheet_view_controller_unittest.mm
@@ -21,7 +21,6 @@
 #import "third_party/ocmock/OCMock/OCMock.h"
 #import "third_party/ocmock/gtest_support.h"
 #import "ui/base/l10n/l10n_util.h"
-#import "url/gurl.h"
 
 // Tests for PasskeyCreationBottomSheetViewController.
 class PasskeyCreationBottomSheetViewControllerTest : public PlatformTest {
@@ -42,9 +41,9 @@
 TEST_F(PasskeyCreationBottomSheetViewControllerTest, BasicInformation) {
   NSString* username = @"user";
   NSString* email = @"[email protected]";
-  GURL url("https://example.com");
+  NSString* rpId = @"example.com";
 
-  [view_controller_ setUsername:username email:email url:url];
+  [view_controller_ setUsername:username email:email rpId:rpId];
   [view_controller_ loadView];
   [view_controller_ viewDidLoad];
 
@@ -71,7 +70,7 @@
       base::apple::ObjCCast<UILabel>(labelsStackView.arrangedSubviews[1]);
 
   EXPECT_NSEQ(username, usernameLabel.text);
-  EXPECT_NSEQ(base::SysUTF8ToNSString(url.host()), domainLabel.text);
+  EXPECT_NSEQ(rpId, domainLabel.text);
 
   // Verifies the button stack configuration.
   EXPECT_NSEQ(
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.