Chrome · Passwords
CVE-2026-17997
Logic Error in Passwords
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
TEST_Fcomponents/password_manager/core/browser/password_autofill_manager_unittest.cc |
modified |
Files Changed
components/password_manager/core/browser/password_autofill_manager.cccomponents/password_manager/core/browser/password_autofill_manager_unittest.cc
Patch
From 3bed447aa3fa78a865159d7a0719e4a723e1e30a Mon Sep 17 00:00:00 2001 From: Oleksandr Tara <[email protected]> Date: Thu, 11 Jun 2026 04:53:16 -0700 Subject: [PATCH] Mask credentials from grouped suggestions with a fixed length string in previews. When previewing password suggestions that come from a grouped affiliation, use a fixed 8-character mask instead of a mask based on the actual password length. Fixed: b:521476960 Change-Id: I01cc15f6edc3f79b16946f3d0dfc9770c513434a Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7922492 Commit-Queue: Oleksandr Tara <[email protected]> Reviewed-by: Viktor Semeniuk <[email protected]> Cr-Commit-Position: refs/heads/main@{#1645278} --- diff --git a/components/password_manager/core/browser/password_autofill_manager.cc b/components/password_manager/core/browser/password_autofill_manager.cc index e95d609..67eca40 100644 --- a/components/password_manager/core/browser/password_autofill_manager.cc +++ b/components/password_manager/core/browser/password_autofill_manager.cc @@ -279,9 +279,10 @@ ->IsBiometricAuthenticationBeforeFillingEnabled()) { return; } + size_t password_length = + payload.is_cross_domain ? 8 : payload.backup_password.value().length(); password_manager_driver_->PreviewSuggestion( - payload.username, - std::u16string(payload.backup_password.value().length(), '*')); + payload.username, std::u16string(password_length, '*')); return; } PreviewSuggestion(GetUsernameFromSuggestion(suggestion.main_text.value), @@ -817,9 +818,12 @@ } if (const autofill::PasswordAndMetadata* password_and_metadata = GetPasswordAndMetadataForUsername(username, type)) { + size_t password_length = + password_and_metadata->is_grouped_affiliation + ? 8 + : password_and_metadata->password_value.length(); password_manager_driver_->PreviewSuggestion( - username, - std::u16string(password_and_metadata->password_value.length(), '*')); + username, std::u16string(password_length, '*')); return true; } return false; diff --git a/components/password_manager/core/browser/password_autofill_manager_unittest.cc b/components/password_manager/core/browser/password_autofill_manager_unittest.cc index c6a0485..f1fc6d36 100644 --- a/components/password_manager/core/browser/password_autofill_manager_unittest.cc +++ b/components/password_manager/core/browser/password_autofill_manager_unittest.cc @@ -486,6 +486,18 @@ password_autofill_manager_->PreviewSuggestionForTest(test_username_)); } +TEST_F(PasswordAutofillManagerTest, PreviewGroupedSuggestion) { + fill_data().preferred_login.is_grouped_affiliation = true; + TestPasswordManagerClient client; + InitializePasswordAutofillManager(&client, nullptr); + + // Grouped suggestions should be masked using an 8-character long mask. + EXPECT_CALL(*client.mock_driver(), + PreviewSuggestion(test_username_, std::u16string(8, '*'))); + EXPECT_TRUE( + password_autofill_manager_->PreviewSuggestionForTest(test_username_)); +} + // Test that the popup is marked as visible after receiving password // suggestions. TEST_F(PasswordAutofillManagerTest, ExternalDelegatePasswordSuggestions) { @@ -2431,6 +2443,26 @@ PasswordRecoveryState::kRegularFlow); } +TEST_F(PasswordAutofillManagerTest, + PasswordRecoveryFlow_PreviewGroupedBackupSuggestion) { + TestPasswordManagerClient client; + InitializePasswordAutofillManager(&client, nullptr); + const Suggestion::PasswordSuggestionDetails payload( + test_username_, test_password_, backup_password_, + /*signon_realm=*/"", /*is_cross_domain=*/true); + const Suggestion suggestion = autofill::test::CreateAutofillSuggestion( + autofill::SuggestionType::kBackupPasswordEntry, test_username_, payload); + + // Grouped backup suggestions should be masked using an 8-character long mask. + EXPECT_CALL(*client.mock_driver(), + PreviewSuggestion(test_username_, std::u16string(8, '*'))); + password_autofill_manager_->DidSelectSuggestion(suggestion); + testing::Mock::VerifyAndClearExpectations(client.mock_driver()); + + EXPECT_EQ(client.GetUndoPasswordChangeController()->GetState(test_username_), + PasswordRecoveryState::kRegularFlow); +} + TEST_F( PasswordAutofillManagerTest, PasswordRecoveryFlow_AuthBeforeFillingEnabled_NoPreviewBackupSuggestion) {
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/components/password_manager/core/browser/password_autofill_manager_unittest.cc b/components/password_manager/core/browser/password_autofill_manager_unittest.cc
index c6a0485..f1fc6d36 100644
--- a/components/password_manager/core/browser/password_autofill_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_autofill_manager_unittest.cc
@@ -486,6 +486,18 @@
password_autofill_manager_->PreviewSuggestionForTest(test_username_));
}
+TEST_F(PasswordAutofillManagerTest, PreviewGroupedSuggestion) {
+ fill_data().preferred_login.is_grouped_affiliation = true;
+ TestPasswordManagerClient client;
+ InitializePasswordAutofillManager(&client, nullptr);
+
+ // Grouped suggestions should be masked using an 8-character long mask.
+ EXPECT_CALL(*client.mock_driver(),
+ PreviewSuggestion(test_username_, std::u16string(8, '*')));
+ EXPECT_TRUE(
+ password_autofill_manager_->PreviewSuggestionForTest(test_username_));
+}
+
// Test that the popup is marked as visible after receiving password
// suggestions.
TEST_F(PasswordAutofillManagerTest, ExternalDelegatePasswordSuggestions) {
@@ -2431,6 +2443,26 @@
PasswordRecoveryState::kRegularFlow);
}
+TEST_F(PasswordAutofillManagerTest,
+ PasswordRecoveryFlow_PreviewGroupedBackupSuggestion) {
+ TestPasswordManagerClient client;
+ InitializePasswordAutofillManager(&client, nullptr);
+ const Suggestion::PasswordSuggestionDetails payload(
+ test_username_, test_password_, backup_password_,
+ /*signon_realm=*/"", /*is_cross_domain=*/true);
+ const Suggestion suggestion = autofill::test::CreateAutofillSuggestion(
+ autofill::SuggestionType::kBackupPasswordEntry, test_username_, payload);
+
+ // Grouped backup suggestions should be masked using an 8-character long mask.
+ EXPECT_CALL(*client.mock_driver(),
+ PreviewSuggestion(test_username_, std::u16string(8, '*')));
+ password_autofill_manager_->DidSelectSuggestion(suggestion);
+ testing::Mock::VerifyAndClearExpectations(client.mock_driver());
+
+ EXPECT_EQ(client.GetUndoPasswordChangeController()->GetState(test_username_),
+ PasswordRecoveryState::kRegularFlow);
+}
+
TEST_F(
PasswordAutofillManagerTest,
PasswordRecoveryFlow_AuthBeforeFillingEnabled_NoPreviewBackupSuggestion) {
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