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 <otara@google.com>
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 <otara@google.com>
Reviewed-by: Viktor Semeniuk <vsemeniuk@google.com>
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