diff --git a/components/password_manager/core/browser/password_reuse_detector_impl.cc b/components/password_manager/core/browser/password_reuse_detector_impl.cc index f7510a7c6f649..583db6fcd0f68 100644 --- a/components/password_manager/core/browser/password_reuse_detector_impl.cc +++ b/components/password_manager/core/browser/password_reuse_detector_impl.cc @@ -249,8 +249,17 @@ PasswordReuseDetectorImpl::CheckSavedPasswordReuseBasedOnHash( pwd_lengths.insert(it.second.password_length); } - const std::string registry_controlled_domain = - GetRegistryControlledDomain(GURL(domain)); + // eTLD+1 is empty for IP literals, single-label hosts, and registry-only + // hosts. Fall back to the literal host so that two unrelated IP addresses are + // not treated as the same domain. + auto effective_domain = [](const GURL& url) -> std::string { + std::string d = GetRegistryControlledDomain(url); + if (d.empty()) { + d = std::string(url.host()); + } + return d; + }; + const std::string registry_controlled_domain = effective_domain(GURL(domain)); // Goes over all possible password lengths and checks input suffix of that // length against known password hashes. @@ -275,11 +284,12 @@ PasswordReuseDetectorImpl::CheckSavedPasswordReuseBasedOnHash( std::set domains; for (const auto& credential : credentials) { - domains.insert(GetRegistryControlledDomain(credential.url)); + domains.insert(effective_domain(credential.url)); } // If the page's URL matches a saved domain for this password, // this isn't password-reuse. - if (domains.contains(registry_controlled_domain)) { + if (!registry_controlled_domain.empty() && + domains.contains(registry_controlled_domain)) { continue; }