Overview

High
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactIncorrect security UI in Passwords
DescriptionIncorrect security UI in Passwords
ComponentPasswords
Bug ClassLogic Error
Tracker517258337
Fix commitb1f5d7fbf510 (chromium/src) +12/-0
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-16

Files Changed

  • chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
  • chrome/browser/ui/views/passwords/account_chooser_dialog_view.h
  • chrome/browser/ui/views/passwords/password_combined_selector_view.cc
  • chrome/browser/ui/views/passwords/password_combined_selector_view.h
From b1f5d7fbf5101101bf1015f729535d13285be0cc Mon Sep 17 00:00:00 2001
From: Adem Derinel <[email protected]>
Date: Tue, 09 Jun 2026 06:37:46 -0700
Subject: [PATCH] Disable key events during input protection in get() password dialogs

Overrode ShouldAllowKeyEventsDuringInputProtection() to return false in
AccountChooserDialogView and PasswordCombinedSelectorView.

Fixed: 517258337
Change-Id: I67f727a5d9c898380c0887b3ac40cd08bee09f96
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7911384
Commit-Queue: Adem Derinel <[email protected]>
Reviewed-by: Mohamed Amir Yosef <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1643913}
---

diff --git a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
index 9a1ac17..ac0f3e9 100644
--- a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
+++ b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
@@ -116,6 +116,11 @@
   return false;
 }
 
+bool AccountChooserDialogView::ShouldAllowKeyEventsDuringInputProtection()
+    const {
+  return false;
+}
+
 void AccountChooserDialogView::InitWindow() {
   auto contents_view = std::make_unique<views::View>();
   contents_view->SetLayoutManager(std::make_unique<views::FillLayout>());
diff --git a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.h b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.h
index bb8589b..8201511 100644
--- a/chrome/browser/ui/views/passwords/account_chooser_dialog_view.h
+++ b/chrome/browser/ui/views/passwords/account_chooser_dialog_view.h
@@ -35,6 +35,7 @@
 
   // DialogDelegate:
   bool Accept() override;
+  bool ShouldAllowKeyEventsDuringInputProtection() const override;
 
  private:
   std::u16string GetWindowTitle() const override;
diff --git a/chrome/browser/ui/views/passwords/password_combined_selector_view.cc b/chrome/browser/ui/views/passwords/password_combined_selector_view.cc
index 6da03ed..6181727 100644
--- a/chrome/browser/ui/views/passwords/password_combined_selector_view.cc
+++ b/chrome/browser/ui/views/passwords/password_combined_selector_view.cc
@@ -522,6 +522,11 @@
   return false;
 }
 
+bool PasswordCombinedSelectorView::ShouldAllowKeyEventsDuringInputProtection()
+    const {
+  return false;
+}
+
 void PasswordCombinedSelectorView::InitWindow() {
   auto main_view = std::make_unique<PasswordCombinedSelectorViewWrapper>();
   main_view->SetLayoutManager(std::make_unique<views::FillLayout>());
diff --git a/chrome/browser/ui/views/passwords/password_combined_selector_view.h b/chrome/browser/ui/views/passwords/password_combined_selector_view.h
index b8d360c..33cc9f4 100644
--- a/chrome/browser/ui/views/passwords/password_combined_selector_view.h
+++ b/chrome/browser/ui/views/passwords/password_combined_selector_view.h
@@ -49,6 +49,7 @@
 
   // views::DialogDelegate:
   bool Accept() override;
+  bool ShouldAllowKeyEventsDuringInputProtection() const override;
 
   const std::vector<raw_ptr<views::RadioButton>>& GetRadioButtonsForTesting()
       const {
Loading diff…

Original Bug Report

reported by [email protected]

Keyjacking in Credential Management chooser discloses cross-origin passwords

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: The Credential Management API account chooser dialogue views are potentially vulnerable to keyjacking because the default ‘Sign in’ (OK) button is focused automatically upon display and key events bypass input activation protection. An attacker-controlled PSL-matched or affiliated origin can request credentials without transient user activation, then hijack a rapid user keystroke (such as Enter or Space) to instantly accept the prompt. This potentially releases the victim’s saved cross-origin password in cleartext to the requesting page’s renderer.

Affected files:

  • chrome/browser/ui/views/passwords/account_chooser_dialog_view.cc
  • chrome/browser/ui/views/passwords/password_combined_selector_view.cc

Estimated timestamp from git blame: 2026-02-10

Root Cause Analysis

The navigator.credentials.get({password:true}) account-chooser dialog (AccountChooserDialogView and its unified UI replacement PasswordCombinedSelectorView) is a security-decision UI that releases a saved password for a different origin (PSL-matched or affiliation-grouped) to the requesting page.

Two critical details make these dialog views potentially vulnerable to keyjacking:

  1. The OK (‘Sign in’) button is default-focused upon showing.
  2. Key events bypass the InputEventActivationProtector minimum-show-time safety gate.

Neither view overrides GetInitiallyFocusedView(). As a result, the default implementation of DialogDelegate::GetInitiallyFocusedView() is executed and focuses the default OK button initially:

// ui/views/window/dialog_delegate.cc
View* DialogDelegate::GetInitiallyFocusedView() {
  ...
  int default_button = GetDefaultDialogButton();   // returns kOk
  ...
  if (default_button & static_cast<int>(ui::mojom::DialogButton::kOk)) {
    return dcv->ok_button();                       // OK is initially focused
  }
}

Furthermore, neither view overrides ShouldAllowKeyEventsDuringInputProtection(), which defaults to returning true. During dialog interaction, DialogClientView::ButtonPressed calls InputEventActivationProtector::IsPossiblyUnintendedInteraction with allow_key_events=true:

// ui/views/window/dialog_client_view.cc
void DialogClientView::ButtonPressed(ui::mojom::DialogButton type,
                                     const ui::Event& event) {
  ...
  if (... input_protector_->IsPossiblyUnintendedInteraction(
          event, /*allow_key_events=*/delegate
                     ->ShouldAllowKeyEventsDuringInputProtection())) {
    return;
  }
  ... delegate->AcceptDialog();
}

In InputEventActivationProtector::IsPossiblyUnintendedInteraction, non-repeat key events with allow_key_events=true immediately return false, meaning they completely bypass the minimum-show-time safety gate (view_protected_time_stamp_ is never checked against):

// ui/views/input_event_activation_protector.cc
if (event.IsKeyEvent() && event.AsKeyEvent()->is_repeat()) { return true; }
if (!event.IsMouseEvent() && !event.IsTouchEvent() && !event.IsGestureEvent()) {
  if (allow_key_events || !event.IsKeyEvent()) {
    return false;   // non-repeat key event: NOT gated by minimum-show-time protector
  }
}

This behavior allows a page sharing the same registerable domain (or affiliation group) to steal credentials via a single rapid, socially-engineered keypress.

Potential Attack Scenario

Note: These are potential steps, as our tooling agent doesn’t yet have the ability to run code or verify a full proof-of-concept.

  1. The user has saved credentials for login.example.com.
  2. The user navigates to an attacker-controlled page sharing the same eTLD+1 (e.g., attacker.example.com).
  3. The attacker page calls navigator.credentials.get({password:true, mediation:'required'}) to query credentials without needing a transient user activation gate.
  4. The browser gathers matched credentials, detects a Public Suffix List (PSL) match, and decides to display the account chooser dialog (since automated sign-in is disallowed for non-exact matches).
  5. The dialog is shown and takes active keyboard focus, defaulting its focus directly onto the ‘Sign in’ (OK) button.
  6. The attacker page presents a call-to-action (e.g., asking the user to “Press Enter to continue”). When the user presses Enter, the key event is targeted directly at the focused ‘Sign in’ button of the dialog.
  7. The keypress completely bypasses the activation protector’s short delay gate and immediately triggers acceptance of the dialog, sending the cleartext credential back to the renderer process.

Suggested Remediation

To align the account chooser dialog views with other security-sensitive dialogs in Chromium (such as PasswordCrossDomainConfirmationPopupViewViews):

  1. Avoid default-focusing the OK/Sign-in button. Override GetInitiallyFocusedView() in AccountChooserDialogView and PasswordCombinedSelectorView to focus the Cancel/Close button instead.
  2. Override ShouldAllowKeyEventsDuringInputProtection() to return false so that key events are subject to the same minimum-show-time safety gate as mouse and touch events.

Evaluated with Chrome root at commit: b1520ef4a76878853a31f0943b565e42060edec8


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