Chrome · Related-Website-Sets
CVE-2026-14059
Logic Error in Related-Website-Sets
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Files Changed
chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.ccchrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
Patch
From b718cffa859d24d37ea592172ce97447d54b5c82 Mon Sep 17 00:00:00 2001 From: Chris Fredrickson <[email protected]> Date: Thu, 07 May 2026 11:02:15 -0700 Subject: [PATCH] [RWS] Fix failure to clear rsaFor permissions Fixed: 502363986 Change-Id: If13ece11a835cb5d725e2116d8061c852d3ea299 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7828839 Commit-Queue: Chris Fredrickson <[email protected]> Auto-Submit: Chris Fredrickson <[email protected]> Reviewed-by: Christian Dullweber <[email protected]> Cr-Commit-Position: refs/heads/main@{#1627070} --- diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc index 4e140e65..4ffdec443 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc @@ -1471,8 +1471,14 @@ std::ranges::any_of( filter_builder->GetOrigins(), [&](const url::Origin& origin) -> bool { - return setting.primary_pattern.Matches( - origin.GetURL()) || + // TopLevelStorageAccessPermissionContext creates + // grants using (origin, site) patterns. We explicitly + // use the primary pattern's site here to ensure any + // permission granted to subdomains of an RWS site are + // properly cleared. + return net::SchemefulSite(setting.primary_pattern + .ToRepresentativeUrl()) + .IsSameSiteWith(origin) || setting.secondary_pattern.Matches( origin.GetURL()); }); diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc index 04936d7..8135162 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc @@ -4739,3 +4739,65 @@ testing::Values(FilterOrigins::kByPrimaryUrl, FilterOrigins::kBySecondaryUrl, FilterOrigins::kByBothUrls))); + +// Regression test for https://crbug.com/502363986. +TEST_F(ChromeBrowsingDataRemoverDelegateTest, + RWSRevocationIncludesSubdomainKeyedRSAForGrants) { + HostContentSettingsMap* settings_map = + HostContentSettingsMapFactory::GetForProfile(GetProfile()); + + // a.test & b.test are assumed to be in an RWS together, but b.test will be + // removed from the set and have its data cleared. + const GURL kTopLevel("https://a.test"); + const GURL kRequestedSubdomain("https://accounts.b.test"); + + content_settings::ContentSettingConstraints rws_constraints; + rws_constraints.set_lifetime(base::Days(30)); + rws_constraints.set_decided_by_related_website_sets(true); + settings_map->SetContentSettingDefaultScope( + kRequestedSubdomain, kTopLevel, + ContentSettingsType::TOP_LEVEL_STORAGE_ACCESS, CONTENT_SETTING_ALLOW, + rws_constraints); + settings_map->SetContentSettingCustomScope( + ContentSettingsPattern::FromURLNoWildcard(kRequestedSubdomain), + ContentSettingsPattern::FromURLToSchemefulSitePattern(kTopLevel), + ContentSettingsType::STORAGE_ACCESS, CONTENT_SETTING_ALLOW, + rws_constraints); + + // 1 wildcard setting each, plus 1 specific setting each. + ASSERT_EQ( + settings_map->GetSettingsForOneType(ContentSettingsType::STORAGE_ACCESS) + .size(), + 2u); + ASSERT_EQ( + settings_map + ->GetSettingsForOneType(ContentSettingsType::TOP_LEVEL_STORAGE_ACCESS) + .size(), + 2u); + + std::unique_ptr<BrowsingDataFilterBuilder> filter_builder( + BrowsingDataFilterBuilder::Create( + BrowsingDataFilterBuilder::Mode::kDelete)); + // RWS data clearing is site-based (see FirstPartySetsSiteDataRemover). + filter_builder->AddOrigin( + url::Origin::Create(net::SchemefulSite(kRequestedSubdomain).GetURL())); + + BlockUntilOriginDataRemoved( + base::Time(), base::Time::Max(), + content::BrowsingDataRemover::DATA_TYPE_RELATED_WEBSITE_SETS_PERMISSIONS, + std::move(filter_builder)); + + EXPECT_EQ( + settings_map + ->GetSettingsForOneType(ContentSettingsType::TOP_LEVEL_STORAGE_ACCESS) + .size(), + 1u); + EXPECT_EQ( + settings_map->GetSettingsForOneType(ContentSettingsType::STORAGE_ACCESS) + .size(), + 1u); + EXPECT_EQ( + settings_map->GetContentSetting(kRequestedSubdomain, kTopLevel, + ContentSettingsType::STORAGE_ACCESS), + CONTENT_SETTING_ASK); +}
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
index 04936d7..8135162 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -4739,3 +4739,65 @@
testing::Values(FilterOrigins::kByPrimaryUrl,
FilterOrigins::kBySecondaryUrl,
FilterOrigins::kByBothUrls)));
+
+// Regression test for https://crbug.com/502363986.
+TEST_F(ChromeBrowsingDataRemoverDelegateTest,
+ RWSRevocationIncludesSubdomainKeyedRSAForGrants) {
+ HostContentSettingsMap* settings_map =
+ HostContentSettingsMapFactory::GetForProfile(GetProfile());
+
+ // a.test & b.test are assumed to be in an RWS together, but b.test will be
+ // removed from the set and have its data cleared.
+ const GURL kTopLevel("https://a.test");
+ const GURL kRequestedSubdomain("https://accounts.b.test");
+
+ content_settings::ContentSettingConstraints rws_constraints;
+ rws_constraints.set_lifetime(base::Days(30));
+ rws_constraints.set_decided_by_related_website_sets(true);
+ settings_map->SetContentSettingDefaultScope(
+ kRequestedSubdomain, kTopLevel,
+ ContentSettingsType::TOP_LEVEL_STORAGE_ACCESS, CONTENT_SETTING_ALLOW,
+ rws_constraints);
+ settings_map->SetContentSettingCustomScope(
+ ContentSettingsPattern::FromURLNoWildcard(kRequestedSubdomain),
+ ContentSettingsPattern::FromURLToSchemefulSitePattern(kTopLevel),
+ ContentSettingsType::STORAGE_ACCESS, CONTENT_SETTING_ALLOW,
+ rws_constraints);
+
+ // 1 wildcard setting each, plus 1 specific setting each.
+ ASSERT_EQ(
+ settings_map->GetSettingsForOneType(ContentSettingsType::STORAGE_ACCESS)
+ .size(),
+ 2u);
+ ASSERT_EQ(
+ settings_map
+ ->GetSettingsForOneType(ContentSettingsType::TOP_LEVEL_STORAGE_ACCESS)
+ .size(),
+ 2u);
+
+ std::unique_ptr<BrowsingDataFilterBuilder> filter_builder(
+ BrowsingDataFilterBuilder::Create(
+ BrowsingDataFilterBuilder::Mode::kDelete));
+ // RWS data clearing is site-based (see FirstPartySetsSiteDataRemover).
+ filter_builder->AddOrigin(
+ url::Origin::Create(net::SchemefulSite(kRequestedSubdomain).GetURL()));
+
+ BlockUntilOriginDataRemoved(
+ base::Time(), base::Time::Max(),
+ content::BrowsingDataRemover::DATA_TYPE_RELATED_WEBSITE_SETS_PERMISSIONS,
+ std::move(filter_builder));
+
+ EXPECT_EQ(
+ settings_map
+ ->GetSettingsForOneType(ContentSettingsType::TOP_LEVEL_STORAGE_ACCESS)
+ .size(),
+ 1u);
+ EXPECT_EQ(
+ settings_map->GetSettingsForOneType(ContentSettingsType::STORAGE_ACCESS)
+ .size(),
+ 1u);
+ EXPECT_EQ(
+ settings_map->GetContentSetting(kRequestedSubdomain, kTopLevel,
+ ContentSettingsType::STORAGE_ACCESS),
+ CONTENT_SETTING_ASK);
+}
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