Chrome · Passwords
CVE-2026-14050
Logic Error in Passwords
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
ifcomponents/password_manager/core/browser/undo_password_change_controller.cc |
modified |
Files Changed
components/password_manager/core/browser/undo_password_change_controller.cccomponents/password_manager/core/browser/undo_password_change_controller_unittest.cc
Patch
From 08456f50839dffaefdf84205548fe537eb434870 Mon Sep 17 00:00:00 2001 From: Oleksandr Tara <[email protected]> Date: Tue, 19 May 2026 01:50:09 -0700 Subject: [PATCH] Ignore grouped affiliations for proactive password recovery. Suggestions from grouped affiliations need to show cross-domain confirmation before filling but to achieve this in the proactive password recovery, we need non-trivial amount of work. Instead, as a quick fix, we can disable proactive recovery for passwords from grouped affiliations. Fixed: b:501708647 Change-Id: I36d0ecbdf03fd0afd14a6fec62f8af38a0759fed Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7854926 Reviewed-by: Viktor Semeniuk <[email protected]> Commit-Queue: Ioana Treib <[email protected]> Reviewed-by: Ioana Treib <[email protected]> Auto-Submit: Oleksandr Tara <[email protected]> Cr-Commit-Position: refs/heads/main@{#1632709} --- diff --git a/components/password_manager/core/browser/undo_password_change_controller.cc b/components/password_manager/core/browser/undo_password_change_controller.cc index d18f18c0..3239365 100644 --- a/components/password_manager/core/browser/undo_password_change_controller.cc +++ b/components/password_manager/core/browser/undo_password_change_controller.cc @@ -30,6 +30,29 @@ constexpr char kPasswordChangeRecoveryFlowStateHistogram[] = "PasswordManager.PasswordChangeRecoveryFlow"; +bool IsFormEligibleForProactiveRecovery( + const StoredCredential* form_best_match, + const std::u16string& failed_password_value) { + if (!form_best_match) { + return false; + } + + if (password_manager_util::GetMatchType(*form_best_match) == + password_manager_util::GetLoginMatchType::kGrouped) { + return false; + } + + if (!form_best_match->GetPasswordBackup()) { + return false; + } + + if (form_best_match->GetPasswordBackup() == failed_password_value) { + return false; + } + + return true; +} + } // namespace UndoPasswordChangeController::UndoPasswordChangeController() = default; @@ -168,9 +191,8 @@ const StoredCredential* form_best_match = password_manager_util::FindCredentialByUsername( form_manager->GetBestMatches(), failed_login_form_->username_value); - if (!form_best_match || !form_best_match->GetPasswordBackup() || - form_best_match->GetPasswordBackup() == - failed_login_form_->password_value) { + if (!IsFormEligibleForProactiveRecovery( + form_best_match, failed_login_form_->password_value)) { FinishObserving(); return; } diff --git a/components/password_manager/core/browser/undo_password_change_controller_unittest.cc b/components/password_manager/core/browser/undo_password_change_controller_unittest.cc index cb3498d3..5b72771e 100644 --- a/components/password_manager/core/browser/undo_password_change_controller_unittest.cc +++ b/components/password_manager/core/browser/undo_password_change_controller_unittest.cc @@ -383,6 +383,22 @@ } TEST_F(UndoPasswordChangeControllerTest, + OnLoginPotentiallyFailed_GroupedAffiliation_Ignored) { + best_match_form_.SetPasswordBackupNote(kBackupPassword); + best_match_form_.match_type = + password_manager::PasswordForm::MatchType::kGrouped; + auto form_manager = CreateFormManager(best_match_form_); + + controller_.OnLoginPotentiallyFailed(&driver_, failed_login_form_); + EXPECT_CALL(driver_, TriggerPasswordRecoverySuggestions).Times(0); + static_cast<PasswordFormManagerObserver*>(&controller_) + ->OnPasswordFormParsed(form_manager.get()); + + EXPECT_EQ(controller_.GetState(kUsername), + PasswordRecoveryState::kRegularFlow); +} + +TEST_F(UndoPasswordChangeControllerTest, FindLoginWithProactiveRecoveryStateNoMatch) { best_match_form_.SetPasswordBackupNote(kBackupPassword); auto form_manager = CreateFormManager(best_match_form_);
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/components/password_manager/core/browser/undo_password_change_controller_unittest.cc b/components/password_manager/core/browser/undo_password_change_controller_unittest.cc
index cb3498d3..5b72771e 100644
--- a/components/password_manager/core/browser/undo_password_change_controller_unittest.cc
+++ b/components/password_manager/core/browser/undo_password_change_controller_unittest.cc
@@ -383,6 +383,22 @@
}
TEST_F(UndoPasswordChangeControllerTest,
+ OnLoginPotentiallyFailed_GroupedAffiliation_Ignored) {
+ best_match_form_.SetPasswordBackupNote(kBackupPassword);
+ best_match_form_.match_type =
+ password_manager::PasswordForm::MatchType::kGrouped;
+ auto form_manager = CreateFormManager(best_match_form_);
+
+ controller_.OnLoginPotentiallyFailed(&driver_, failed_login_form_);
+ EXPECT_CALL(driver_, TriggerPasswordRecoverySuggestions).Times(0);
+ static_cast<PasswordFormManagerObserver*>(&controller_)
+ ->OnPasswordFormParsed(form_manager.get());
+
+ EXPECT_EQ(controller_.GetState(kUsername),
+ PasswordRecoveryState::kRegularFlow);
+}
+
+TEST_F(UndoPasswordChangeControllerTest,
FindLoginWithProactiveRecoveryStateNoMatch) {
best_match_form_.SetPasswordBackupNote(kBackupPassword);
auto form_manager = CreateFormManager(best_match_form_);
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