Chrome · InterestGroups
CVE-2026-79021
Authorization Error in InterestGroups
Overview
Low
Severity
6.5
CVSS
No
Exploited ITW
Fixed
Fix Status
Background
- Protected Audience (FLEDGE) / Interest Groups
- the Privacy Sandbox API (
navigator.joinAdInterestGroup,runAdAuction) that stores interest groups per browser profile and runs on-device ad auctions. It is gated byblink::features::kFledge,kAdInterestGroupAPIandnetwork::features::kInterestGroupStorage. - `ContentBrowserClient::IsInterestGroupAPIAllowed`
- the embedder authorization hook that content consulted before an interest-group operation. Chrome’s override deferred to
PrivacySandboxSettings::IsFledgeAllowedand recorded joins inPageSpecificContentSettings. - `BrowsingDataModel` `kInterestGroup`
- the storage type that let the site-data UI list and delete interest groups through
InterestGroupManager::GetAllInterestGroupDataKeys/RemoveInterestGroupsByDataKey. - Build disconnection
- this commit removes the FLEDGE directories from the build and stubs out the glue code. It is a feature-removal CL, not a targeted check.
Root Cause Analysis
The diff does not add or repair any authorization check. It removes the Protected Audience feature from the build and deletes its Chrome-side glue, including the authorization hook
ChromeContentBrowserClient::IsInterestGroupAPIAllowed itself, OnAuctionComplete, and the interest-group branches of BrowsingDataModel and PrivacySandboxServiceImpl. The code path that lacked authorization (“Missing authorization in InterestGroups”) is inside the FLEDGE backend, whose hunks are not in this diff, so the specific unchecked operation cannot be named from the patch. Making the whole backend dead code removes the vulnerable path, because no interest-group operation, authorized or not, can be reached any more. The remaining edits are consistency cleanup: GetFledgeJoiningEtldPlusOneForDisplay now returns an empty list, the InterestGroupManager dependency is dropped from PrivacySandboxServiceImpl, and WebView no longer disables kInterestGroupStorage, a flag that per this CL no longer gates compiled code (inferred). As a security fix, this is attack-surface removal, not a corrected check.Key insight
The InterestGroups authorization gap is closed by removing the Protected Audience backend from the build, so the unauthorized operation no longer exists. The diff does not show what the missing check was.
Attack Path
- Reach an interest-group operation
before the fix, web content could invoke Protected Audience operations served by the FLEDGE backend. The specific operation lacking authorization is not visible in this diff
(inferred). - Authorization not applied
per the advisory, some interest-group path ran without the required authorization. The gate that normally applied is
ChromeContentBrowserClient::IsInterestGroupAPIAllowed→PrivacySandboxSettings::IsFledgeAllowed, which this diff removes along with the feature. - Effect
the attacker could perform an interest-group action (join, leave, update or read state) without the expected user or site permission. The exact action and its effect are
(inferred). - Post-fix the backend is no longer compiled and the Chrome glue is deleted, so the path cannot be reached.
Impact Assessment
Per the advisory, this is a low-severity missing-authorization issue in InterestGroups, likely a privacy-policy or permission bypass for Protected Audience state in the browser process
(inferred). The diff provides no evidence of memory corruption or code execution and contains nothing about in-the-wild exploitation. Preconditions are the FLEDGE features being enabled for the profile, which this CL makes moot.Changed Functions
| Function | Change | Notes |
|---|---|---|
ifchrome/browser/chrome_content_browser_client.cc |
modified | |
ifchrome/browser/privacy_sandbox/privacy_sandbox_service_impl.cc |
modified | |
forchrome/browser/privacy_sandbox/privacy_sandbox_service_impl.cc |
modified | |
GetCurrentTopTopicschrome/browser/privacy_sandbox/privacy_sandbox_service_impl.cc |
modified | |
PrefServicechrome/browser/privacy_sandbox/privacy_sandbox_service_impl.h |
modified | |
forcomponents/browsing_data/content/browsing_data_model.cc |
modified | |
switchcomponents/browsing_data/content/browsing_data_model.cc |
modified |
Files Changed
BUILD.gnandroid_webview/browser/aw_field_trials.ccchrome/browser/ash/bruschetta/bruschetta_network_context.ccchrome/browser/ash/bruschetta/bruschetta_network_context.hchrome/browser/browsing_data/browsing_data_model_browsertest.ccchrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.ccchrome/browser/chrome_content_browser_client.ccchrome/browser/chrome_content_browser_client.hchrome/browser/privacy_sandbox/privacy_sandbox_service_factory.ccchrome/browser/privacy_sandbox/privacy_sandbox_service_impl.ccchrome/browser/privacy_sandbox/privacy_sandbox_service_impl.hchrome/browser/privacy_sandbox/privacy_sandbox_service_impl_unittest.cccomponents/browsing_data/content/browsing_data_model.cccomponents/browsing_data/content/browsing_data_model.hcomponents/browsing_data/content/browsing_data_model_test_util.cccomponents/browsing_data/content/browsing_data_model_unittest.cccomponents/page_load_metrics/browser/metrics_web_contents_observer.cccomponents/page_load_metrics/browser/metrics_web_contents_observer.hcomponents/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.cccomponents/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.hcomponents/page_load_metrics/browser/observers/ad_metrics/aggregate_frame_data.cccomponents/page_load_metrics/browser/observers/ad_metrics/aggregate_frame_data.hcomponents/page_load_metrics/browser/observers/assert_page_load_metrics_observer.hcomponents/page_load_metrics/browser/page_load_metrics_forward_observer.cccomponents/page_load_metrics/browser/page_load_metrics_forward_observer.hcomponents/page_load_metrics/browser/page_load_metrics_observer.hcomponents/page_load_metrics/browser/page_load_metrics_observer_interface.hcomponents/page_load_metrics/browser/page_load_tracker.cccomponents/page_load_metrics/browser/page_load_tracker.hcomponents/privacy_sandbox/mock_privacy_sandbox_settings.hcomponents/privacy_sandbox/privacy_sandbox_settings.hcomponents/privacy_sandbox/privacy_sandbox_settings_impl.cccomponents/privacy_sandbox/privacy_sandbox_settings_impl.hcomponents/privacy_sandbox/privacy_sandbox_test_util.cccomponents/privacy_sandbox/privacy_sandbox_test_util_unittest.cccontent/DEPScontent/browser/BUILD.gncontent/browser/attribution_reporting/privacy_sandbox_ads_apis_browsertest.cccontent/browser/browser_context.cccontent/browser/browser_interface_binders.cccontent/browser/btm/btm_bounce_detector_browsertest.cccontent/browser/btm/btm_browsertest_utils.cccontent/browser/btm/btm_browsertest_utils.hcontent/browser/devtools/devtools_agent_host_impl.cccontent/browser/devtools/devtools_instrumentation.hcontent/browser/devtools/frame_auto_attacher.cccontent/browser/devtools/frame_auto_attacher.hcontent/browser/devtools/protocol/browser_handler.cccontent/browser/devtools/protocol/storage_handler.cccontent/browser/fenced_frame/fenced_frame_browsertest.cccontent/browser/fenced_frame/fenced_frame_config.cccontent/browser/fenced_frame/fenced_frame_config.hcontent/browser/fenced_frame/fenced_frame_reporter.cccontent/browser/fenced_frame/fenced_frame_reporter.hcontent/browser/fenced_frame/fenced_frame_reporter_unittest.cccontent/browser/fenced_frame/fenced_frame_url_mapping.cccontent/browser/fenced_frame/fenced_frame_url_mapping.hcontent/browser/fenced_frame/fenced_frame_url_mapping_unittest.cccontent/browser/loader/subresource_proxying_url_loader.cccontent/browser/loader/subresource_proxying_url_loader_service.cccontent/browser/network_service_client.cccontent/browser/network_service_client.hcontent/browser/renderer_host/navigation_request.cccontent/browser/renderer_host/navigation_request.hcontent/browser/renderer_host/navigator.cccontent/browser/renderer_host/render_frame_host_impl.cccontent/browser/renderer_host/render_frame_host_impl.hcontent/browser/storage_partition_impl.cccontent/browser/storage_partition_impl.hcontent/browser/storage_partition_impl_unittest.cccontent/child/runtime_features.cccontent/common/BUILD.gncontent/common/features.cccontent/common/features.hcontent/public/browser/BUILD.gncontent/public/browser/browser_context.hcontent/public/browser/content_browser_client.cccontent/public/browser/content_browser_client.hcontent/public/browser/storage_partition.hcontent/public/common/content_switch_dependent_feature_overrides.cccontent/public/test/fenced_frame_test_util.cccontent/public/test/fenced_frame_test_util.hcontent/public/test/privacy_sandbox_coordinator_test_util.cccontent/public/test/privacy_sandbox_coordinator_test_util.hcontent/public/test/test_storage_partition.cccontent/public/test/test_storage_partition.hcontent/renderer/BUILD.gncontent/renderer/DEPScontent/renderer/browser_exposed_renderer_interfaces.cccontent/renderer/render_frame_impl.cccontent/test/BUILD.gncontent/test/fuzzer/BUILD.gncontent/utility/BUILD.gncontent/utility/services.cccontent/web_test/BUILD.gncontent/web_test/browser/web_test_content_browser_client.cccontent/web_test/browser/web_test_content_browser_client.hheadless/lib/browser/headless_content_browser_client.ccheadless/lib/browser/headless_content_browser_client.hremoting/base/url_loader_network_service_observer.ccremoting/base/url_loader_network_service_observer.hservices/network/public/cpp/BUILD.gnservices/network/public/cpp/features.ccservices/network/public/cpp/features.hservices/network/public/mojom/BUILD.gnservices/network/public/mojom/url_loader_network_service_observer.mojomservices/network/test/test_url_loader_network_observer.ccservices/network/test/test_url_loader_network_observer.hthird_party/blink/common/BUILD.gnthird_party/blink/common/features.ccthird_party/blink/public/BUILD.gnthird_party/blink/public/common/BUILD.gnthird_party/blink/public/common/features.hthird_party/blink/public/common/fenced_frame/fenced_frame_utils.hthird_party/blink/public/devtools_protocol/domains/Storage.pdlthird_party/blink/public/mojom/BUILD.gnthird_party/blink/public/mojom/frame/frame.mojomthird_party/blink/public/mojom/shared_storage/shared_storage_worklet_service.mojomthird_party/blink/public/test/mojom/BUILD.gnthird_party/blink/renderer/bindings/idl_in_modules.gnithird_party/blink/renderer/core/html/fenced_frame/fence.ccthird_party/blink/renderer/core/html/fenced_frame/fence_test.ccthird_party/blink/renderer/core/origin_trials/origin_trial_context.ccthird_party/blink/renderer/core/testing/fake_local_frame_host.ccthird_party/blink/renderer/core/testing/fake_local_frame_host.hthird_party/blink/renderer/modules/BUILD.gnthird_party/blink/renderer/modules/ad_auction/BUILD.gnthird_party/blink/renderer/platform/runtime_enabled_features.json5third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.pytools/metrics/histograms/enums.xmltools/metrics/histograms/metadata/history/enums.xmltools/metrics/histograms/metadata/network/histograms.xmltools/metrics/histograms/metadata/others/enums.xmltools/metrics/histograms/metadata/others/histograms.xmltools/metrics/histograms/metadata/page/histograms.xmltools/metrics/private_metrics/dwa.xml
Audit Directions
- Partial removal leaving reachable stubscheck that every renderer-exposed binder (
content/renderer/browser_exposed_renderer_interfaces.cc,RenderFrameHostImplinterface registration, fenced-frame config paths) that used to reach FLEDGE is either unregistered or rejects calls. A stub that still accepts calls, or that skips a check that used to live in the removed backend, would reintroduce the issue. - Orphaned persisted state and clearing UI
BrowsingDataModelno longer lists or deleteskInterestGroupdata, andGetFledgeJoiningEtldPlusOneForDisplayreturns empty. Verify that on-disk interest-group databases from earlier versions are deleted, and are not left in place where the user can no longer see or clear them. - Authorization hooks that only one feature consultedfor the remaining Privacy Sandbox APIs (Shared Storage, Topics, Attribution Reporting), audit that each browser-side entry point calls its
ContentBrowserClient::Is*Allowedhook on every operation, including updates, leave or clear calls, and header-driven paths such asOn*HeaderReceived, not only on the initial join or write.
Patch
diff --git a/android_webview/browser/aw_field_trials.cc b/android_webview/browser/aw_field_trials.cc
index f81fce6f..b80969b 100644
--- a/android_webview/browser/aw_field_trials.cc
+++ b/android_webview/browser/aw_field_trials.cc
@@ -108,7 +108,6 @@
aw_feature_overrides.DisableFeature(blink::features::kFencedFrames);
// Disable FLEDGE on WebView.
- aw_feature_overrides.DisableFeature(network::features::kInterestGroupStorage);
aw_feature_overrides.DisableFeature(blink::features::kAdInterestGroupAPI);
aw_feature_overrides.DisableFeature(blink::features::kFledge);
diff --git a/chrome/browser/ash/bruschetta/bruschetta_network_context.cc b/chrome/browser/ash/bruschetta/bruschetta_network_context.cc
index cd7b0ecfc..c1956cb 100644
--- a/chrome/browser/ash/bruschetta/bruschetta_network_context.cc
+++ b/chrome/browser/ash/bruschetta/bruschetta_network_context.cc
@@ -275,10 +275,6 @@
std::move(callback).Run();
}
-void BruschettaNetworkContext::OnAdAuctionEventRecordHeaderReceived(
- network::AdAuctionEventRecord event_record,
- const std::optional<url::Origin>& top_frame_origin) {}
-
void BruschettaNetworkContext::Clone(
mojo::PendingReceiver<network::mojom::URLLoaderNetworkServiceObserver>
observer) {
diff --git a/chrome/browser/ash/bruschetta/bruschetta_network_context.h b/chrome/browser/ash/bruschetta/bruschetta_network_context.h
index 73922b6..e396891b 100644
--- a/chrome/browser/ash/bruschetta/bruschetta_network_context.h
+++ b/chrome/browser/ash/bruschetta/bruschetta_network_context.h
@@ -93,9 +93,6 @@
methods_with_options,
const std::optional<std::string>& with_lock,
OnSharedStorageHeaderReceivedCallback callback) override;
- void OnAdAuctionEventRecordHeaderReceived(
- network::AdAuctionEventRecord event_record,
- const std::optional<url::Origin>& top_frame_origin) override;
void Clone(
mojo::PendingReceiver<network::mojom::URLLoaderNetworkServiceObserver>
listener) override;
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index fcfa3bd..422f6d99f 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -3604,32 +3604,7 @@
storage_key);
}
-bool ChromeContentBrowserClient::IsInterestGroupAPIAllowed(
- content::BrowserContext* browser_context,
- content::RenderFrameHost* render_frame_host,
- InterestGroupApiOperation operation,
- const url::Origin& top_frame_origin,
- const url::Origin& api_origin) {
- Profile* profile = Profile::FromBrowserContext(browser_context);
- auto* privacy_sandbox_settings =
- PrivacySandboxSettingsFactory::GetForProfile(profile);
- DCHECK(privacy_sandbox_settings);
- bool allowed = privacy_sandbox_settings->IsFledgeAllowed(
- top_frame_origin, api_origin, operation, render_frame_host);
-
- if (operation == InterestGroupApiOperation::kJoin) {
- content_settings::PageSpecificContentSettings::InterestGroupJoined(
- render_frame_host, api_origin, !allowed);
- content_settings::PageSpecificContentSettings::BrowsingDataAccessed(
- render_frame_host,
- content::InterestGroupManager::InterestGroupDataKey{api_origin,
- top_frame_origin},
- BrowsingDataModel::StorageType::kInterestGroup, !allowed);
- }
-
- return allowed;
-}
bool ChromeContentBrowserClient::IsPrivacySandboxReportingDestinationAttested(
content::BrowserContext* browser_context,
@@ -3658,27 +3633,6 @@
destination_origin, gated_api);
}
-void ChromeContentBrowserClient::OnAuctionComplete(
- content::RenderFrameHost* render_frame_host,
- std::optional<content::InterestGroupManager::InterestGroupDataKey>
- winner_data_key,
- bool is_server_auction,
- bool is_on_device_auction,
- content::AuctionResult result) {
- if (winner_data_key) {
- content_settings::PageSpecificContentSettings::BrowsingDataAccessed(
- render_frame_host, winner_data_key.value(),
- BrowsingDataModel::StorageType::kInterestGroup,
- /*blocked=*/false);
- }
- if (auto* observer =
- page_load_metrics::MetricsWebContentsObserver::FromWebContents(
- WebContents::FromRenderFrameHost(render_frame_host))) {
- observer->OnAdAuctionComplete(render_frame_host, is_server_auction,
- is_on_device_auction, result);
- }
-}
-
bool ChromeContentBrowserClient::IsSharedStorageAllowed(
content::BrowserContext* browser_context,
content::RenderFrameHost* rfh,
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 1bb63d817..85e253f 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -397,22 +397,11 @@
content::BrowserContext* browser_context,
const std::vector<content::GlobalRenderFrameHostId>& render_frames,
const blink::StorageKey& storage_key) override;
- bool IsInterestGroupAPIAllowed(content::BrowserContext* browser_context,
- content::RenderFrameHost* render_frame_host,
- InterestGroupApiOperation operation,
- const url::Origin& top_frame_origin,
- const url::Origin& api_origin) override;
+
bool IsPrivacySandboxReportingDestinationAttested(
content::BrowserContext* browser_context,
const url::Origin& destination_origin,
content::PrivacySandboxInvokingAPI invoking_api) override;
- void OnAuctionComplete(
- content::RenderFrameHost* render_frame_host,
- std::optional<content::InterestGroupManager::InterestGroupDataKey>
- winner_data_key,
- bool is_server_auction,
- bool is_on_device_auction,
- content::AuctionResult result) override;
// TODO(crbug.com/369436599): Remove the default arguments in virtual methods.
bool IsSharedStorageAllowed(
content::BrowserContext* browser_context,
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.cc
index 10851db..46c6a74 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.cc
@@ -83,7 +83,6 @@
return std::make_unique<PrivacySandboxServiceImpl>(
profile, PrivacySandboxSettingsFactory::GetForProfile(profile),
CookieSettingsFactory::GetForProfile(profile), profile->GetPrefs(),
- profile->GetDefaultStoragePartition()->GetInterestGroupManager(),
GetProfileType(profile),
(!profile->IsGuestSession() || profile->IsOffTheRecord())
? profile->GetBrowsingDataRemover()
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl.cc
index 189a341..cc2d8fb 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl.cc
@@ -31,7 +31,6 @@
#include "components/url_formatter/url_formatter.h"
#include "content/public/browser/browsing_data_filter_builder.h"
#include "content/public/browser/browsing_data_remover.h"
-#include "content/public/browser/interest_group_manager.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/base/schemeful_site.h"
#include "net/first_party_sets/first_party_set_entry.h"
@@ -174,11 +173,6 @@
});
}
-void RecordProtectedAudienceJoiningTopFrameDisplayedHistogram(bool value) {
- base::UmaHistogramBoolean(
- "PrivacySandbox.ProtectedAudience.JoiningTopFrameDisplayed", value);
-}
-
// Emits startup histograms relating to the user's topics enabled status on
// both client and profile level.
void RecordTopicsEnabledHistograms(Profile* profile, bool enabled) {
@@ -230,7 +224,6 @@
privacy_sandbox::PrivacySandboxSettings* privacy_sandbox_settings,
scoped_refptr<content_settings::CookieSettings> cookie_settings,
PrefService* pref_service,
- content::InterestGroupManager* interest_group_manager,
profile_metrics::BrowserProfileType profile_type,
content::BrowsingDataRemover* browsing_data_remover,
HostContentSettingsMap* host_content_settings_map,
@@ -241,7 +234,6 @@
privacy_sandbox_settings_(privacy_sandbox_settings),
cookie_settings_(cookie_settings),
pref_service_(pref_service),
- interest_group_manager_(interest_group_manager),
profile_type_(profile_type),
browsing_data_remover_(browsing_data_remover),
host_content_settings_map_(host_content_settings_map),
@@ -316,7 +308,6 @@
browsing_topics_service_ = nullptr;
host_content_settings_map_ = nullptr;
browsing_data_remover_ = nullptr;
- interest_group_manager_ = nullptr;
pref_service_ = nullptr;
cookie_settings_ = nullptr;
privacy_sandbox_settings_ = nullptr;
@@ -389,14 +380,7 @@
void PrivacySandboxServiceImpl::GetFledgeJoiningEtldPlusOneForDisplay(
base::OnceCallback<void(std::vector<std::string>)> callback) {
- if (!interest_group_manager_) {
- std::move(callback).Run({});
- return;
- }
-
- interest_group_manager_->GetAllInterestGroupDataKeys(base::BindOnce(
- &PrivacySandboxServiceImpl::ConvertInterestGroupDataKeysForDisplay,
- weak_factory_.GetWeakPtr(), std::move(callback)));
+ std::move(callback).Run({});
}
std::vector<std::string>
@@ -473,49 +457,6 @@
RecordAdMeasurementEnabledHistograms(profile_, ad_measurement_enabled);
}
-void PrivacySandboxServiceImpl::ConvertInterestGroupDataKeysForDisplay(
- base::OnceCallback<void(std::vector<std::string>)> callback,
- std::vector<content::InterestGroupManager::InterestGroupDataKey>
- data_keys) {
- std::set<std::string> display_entries;
- for (const auto& data_key : data_keys) {
- // When displaying interest group information in settings, the joining
- // origin is the relevant origin.
- const auto& origin = data_key.joining_origin;
-
- // Prefer to display the associated eTLD+1, if there is one.
- auto etld_plus_one = net::registry_controlled_domains::GetDomainAndRegistry(
- origin, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
- if (etld_plus_one.length() > 0) {
- display_entries.emplace(std::move(etld_plus_one));
- RecordProtectedAudienceJoiningTopFrameDisplayedHistogram(true);
- continue;
- }
-
- // The next best option is a host, which may be an IP address or an eTLD
- // itself (e.g. github.io).
- if (origin.host().length() > 0) {
- display_entries.emplace(origin.host());
- RecordProtectedAudienceJoiningTopFrameDisplayedHistogram(true);
- continue;
- }
-
- // By design, each interest group should have a joining site or host, and
- // so this could ideally be a NOTREACHED(). However, following
- // crbug.com/40933994, it is apparent that this is not always true.
- // A host or site is expected in other parts of the UI, so we cannot
- // simply display the origin directly (it may also be empty). Instead, we
- // elide it but record a metric to understand how widespread this is.
- // TODO(crbug.com/40283983) - Investigate how much of an issue this is.
- RecordProtectedAudienceJoiningTopFrameDisplayedHistogram(false);
- }
-
- // Entries should be displayed alphabetically, as |display_entries| is a
- // std::set<std::string>, entries are already ordered correctly.
- std::move(callback).Run(
- std::vector<std::string>{display_entries.begin(), display_entries.end()});
-}
-
std::vector<privacy_sandbox::CanonicalTopic>
PrivacySandboxServiceImpl::GetCurrentTopTopics() const {
if (pref_service_->GetBoolean(prefs::kPrivacySandboxM1TopicsEnabled) &&
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl.h b/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl.h
index fe259c4..7811cc7a 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl.h
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl.h
@@ -21,7 +21,6 @@
#include "components/privacy_sandbox/canonical_topic.h"
#include "components/privacy_sandbox/privacy_sandbox_settings.h"
#include "components/profile_metrics/browser_profile_type.h"
-#include "content/public/browser/interest_group_manager.h"
#include "net/base/schemeful_site.h"
class PrefService;
@@ -45,7 +44,6 @@
privacy_sandbox::PrivacySandboxSettings* privacy_sandbox_settings,
scoped_refptr<content_settings::CookieSettings> cookie_settings,
PrefService* pref_service,
- content::InterestGroupManager* interest_group_manager,
profile_metrics::BrowserProfileType profile_type,
content::BrowsingDataRemover* browsing_data_remover,
HostContentSettingsMap* host_content_settings_map,
@@ -146,13 +144,6 @@
// Called once per profile startup.
void LogPrivacySandboxState();
- // Converts the provided list of |top_frames| into eTLD+1s for display, and
- // provides those to |callback|.
- void ConvertInterestGroupDataKeysForDisplay(
- base::OnceCallback<void(std::vector<std::string>)> callback,
- std::vector<content::InterestGroupManager::InterestGroupDataKey>
- data_keys);
-
// Checks to see if initialization of the user's RWS pref is required, and if
// so, sets the default value based on the user's current cookie settings.
void MaybeInitializeRelatedWebsiteSetsPref();
@@ -174,7 +165,6 @@
raw_ptr<privacy_sandbox::PrivacySandboxSettings> privacy_sandbox_settings_;
scoped_refptr<content_settings::CookieSettings> cookie_settings_;
raw_ptr<PrefService> pref_service_;
- raw_ptr<content::InterestGroupManager> interest_group_manager_;
profile_metrics::BrowserProfileType profile_type_;
raw_ptr<content::BrowsingDataRemover> browsing_data_remover_;
raw_ptr<HostContentSettingsMap> host_content_settings_map_;
diff --git a/components/browsing_data/content/browsing_data_model.cc b/components/browsing_data/content/browsing_data_model.cc
index c30b275..299c85c 100644
--- a/components/browsing_data/content/browsing_data_model.cc
+++ b/components/browsing_data/content/browsing_data_model.cc
@@ -39,7 +39,6 @@
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/trust_tokens.mojom.h"
#include "third_party/abseil-cpp/absl/functional/overload.h"
-#include "third_party/blink/public/common/interest_group/interest_group.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "url/origin.h"
#include "url/url_util.h"
@@ -50,8 +49,6 @@
// imperceptible, but non-0 amount of space, such as Trust Tokens.
constexpr int kSmallAmountOfDataInBytes = 100;
-// An estimate of storage size of an Interest Group object.
-constexpr int kModerateAmountOfDataInBytes = 1024;
// Visitor which returns the appropriate data owner for a given `data_key`
// and `storage_type`.
@@ -128,13 +125,6 @@
return GetOwnerBasedOnScheme(session_storage_usage_info.storage_key.origin());
}
-template <>
-BrowsingDataModel::DataOwner GetDataOwner::GetOwningOriginOrHost<
- content::InterestGroupManager::InterestGroupDataKey>(
- const content::InterestGroupManager::InterestGroupDataKey& data_key) const {
- CHECK_EQ(BrowsingDataModel::StorageType::kInterestGroup, storage_type_);
- return GetOwnerBasedOnScheme(data_key.owner);
-}
template <>
BrowsingDataModel::DataOwner
@@ -278,19 +268,6 @@
}
}
-template <>
-void StorageRemoverHelper::Visitor::operator()<
- content::InterestGroupManager::InterestGroupDataKey>(
- const content::InterestGroupManager::InterestGroupDataKey& data_key) {
- CHECK(types.Has(BrowsingDataModel::StorageType::kInterestGroup));
- helper->storage_partition_->GetInterestGroupManager()
- ->RemoveInterestGroupsByDataKey(
- data_key, base::BindOnce(
- [](base::OnceClosure complete_callback) {
- std::move(complete_callback).Run();
- },
- helper->GetCompleteCallback()));
-}
template <>
void StorageRemoverHelper::Visitor::operator()<
@@ -408,18 +385,6 @@
}
-void OnInterestGroupsLoaded(
- BrowsingDataModel* model,
- base::OnceClosure loaded_callback,
- std::vector<content::InterestGroupManager::InterestGroupDataKey>
- interest_groups) {
- for (const auto& data_key : interest_groups) {
- model->AddBrowsingData(data_key,
- BrowsingDataModel::StorageType::kInterestGroup,
- kModerateAmountOfDataInBytes);
- }
- std::move(loaded_callback).Run();
-}
void OnQuotaStorageLoaded(
BrowsingDataModel* model,
@@ -513,7 +478,6 @@
std::visit(
absl::Overload{
[&](const url::Origin&) {},
- [&](const content::InterestGroupManager::InterestGroupDataKey) {},
[&](const blink::StorageKey& storage_key) {
if (storage_key.IsThirdPartyContext()) {
top_level_site = storage_key.top_level_site();
@@ -583,8 +547,6 @@
return std::visit(
absl::Overload{
[](const url::Origin& origin) { return origin; },
- [](const content::InterestGroupManager::InterestGroupDataKey
- interest_group_key) { return interest_group_key.owner; },
[](const blink::StorageKey& storage_key) {
return storage_key.origin();
},
@@ -854,7 +816,6 @@
switch (storage_type) {
case BrowsingDataModel::StorageType::kTrustTokens:
- case BrowsingDataModel::StorageType::kInterestGroup:
case BrowsingDataModel::StorageType::kSharedDictionary:
return false;
... (file diff truncated)
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/chrome/browser/browsing_data/browsing_data_model_browsertest.cc b/chrome/browser/browsing_data/browsing_data_model_browsertest.cc
index 332214e..af3166e 100644
--- a/chrome/browser/browsing_data/browsing_data_model_browsertest.cc
+++ b/chrome/browser/browsing_data/browsing_data_model_browsertest.cc
@@ -386,9 +386,6 @@
{features::kIsolatedWebApps, {}},
{features::kIsolatedWebAppDevMode, {}},
{network::features::kSharedStorageAPI, {}},
- {network::features::kInterestGroupStorage, {}},
- {blink::features::kAdInterestGroupAPI, {}},
- {blink::features::kFledge, {}},
{blink::features::kFencedFrames, {}},
{network::features::kBrowsingTopics, {}},
{net::features::kThirdPartyStoragePartitioning, {}},
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 30c8266..d59988f0 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
@@ -3370,74 +3370,6 @@
net::NetworkAnonymizationKey()));
}
-TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemoveFledgeJoinSettings) {
- auto* privacy_sandbox_settings =
- PrivacySandboxSettingsFactory::GetForProfile(GetProfile());
- privacy_sandbox_settings->SetAllPrivacySandboxAllowedForTesting();
-
- privacy_sandbox::ScopedPrivacySandboxAttestations scoped_attestations(
- privacy_sandbox::PrivacySandboxAttestations::CreateForTesting());
- // Mark all Privacy Sandbox APIs as attested since the test case is testing
- // behaviors not related to attestations.
- privacy_sandbox::PrivacySandboxAttestations::GetInstance()
- ->SetAllPrivacySandboxAttestedForTesting(true);
-
- auto auction_party = url::Origin::Create(GURL("https://auction-party.com"));
-
- const std::string etld_one = "example.com";
- base::Time setting_time_one = base::Time::Now();
- privacy_sandbox_settings->SetFledgeJoiningAllowed(etld_one, false);
- task_environment()->AdvanceClock(base::Days(1));
-
- const std::string etld_two = "another-example.com";
- base::Time setting_time_two = base::Time::Now();
- privacy_sandbox_settings->SetFledgeJoiningAllowed(etld_two, false);
- task_environment()->AdvanceClock(base::Days(1));
-
- const std::string etld_three = "different-example.com";
- base::Time setting_time_three = base::Time::Now();
- privacy_sandbox_settings->SetFledgeJoiningAllowed(etld_three, false);
-
- EXPECT_FALSE(privacy_sandbox_settings->IsFledgeAllowed(
- url::Origin::Create(GURL("https://www.example.com")), auction_party,
- content::InterestGroupApiOperation::kJoin));
- EXPECT_FALSE(privacy_sandbox_settings->IsFledgeAllowed(
- url::Origin::Create(GURL("https://another-example.com")), auction_party,
- content::InterestGroupApiOperation::kJoin));
- EXPECT_FALSE(privacy_sandbox_settings->IsFledgeAllowed(
- url::Origin::Create(GURL("http://different-example.com")), auction_party,
- content::InterestGroupApiOperation::kJoin));
-
- // Apply a deletion targeting the second setting.
- BlockUntilBrowsingDataRemoved(setting_time_two - base::Seconds(1),
- setting_time_two + base::Seconds(1),
- constants::DATA_TYPE_CONTENT_SETTINGS, false);
-
- EXPECT_FALSE(privacy_sandbox_settings->IsFledgeAllowed(
- url::Origin::Create(GURL("https://www.example.com")), auction_party,
- content::InterestGroupApiOperation::kJoin));
- EXPECT_TRUE(privacy_sandbox_settings->IsFledgeAllowed(
- url::Origin::Create(GURL("https://another-example.com")), auction_party,
- content::InterestGroupApiOperation::kJoin));
- EXPECT_FALSE(privacy_sandbox_settings->IsFledgeAllowed(
- url::Origin::Create(GURL("http://different-example.com")), auction_party,
- content::InterestGroupApiOperation::kJoin));
-
- // Apply a deletion targeting the remaining settings.
- BlockUntilBrowsingDataRemoved(setting_time_one, setting_time_three,
- constants::DATA_TYPE_CONTENT_SETTINGS, false);
-
- EXPECT_TRUE(privacy_sandbox_settings->IsFledgeAllowed(
- url::Origin::Create(GURL("https://www.example.com")), auction_party,
- content::InterestGroupApiOperation::kJoin));
- EXPECT_TRUE(privacy_sandbox_settings->IsFledgeAllowed(
- url::Origin::Create(GURL("https://another-example.com")), auction_party,
- content::InterestGroupApiOperation::kJoin));
- EXPECT_TRUE(privacy_sandbox_settings->IsFledgeAllowed(
- url::Origin::Create(GURL("http://different-example.com")), auction_party,
- content::InterestGroupApiOperation::kJoin));
-}
-
TEST_F(ChromeBrowsingDataRemoverDelegateTest, RemoveTopicSettings) {
auto* privacy_sandbox_settings =
PrivacySandboxSettingsFactory::GetForProfile(GetProfile());
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl_unittest.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl_unittest.cc
index 3c7984915..3ea27e3 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl_unittest.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl_unittest.cc
@@ -51,7 +51,6 @@
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/first_party_sets_handler.h"
-#include "content/public/browser/interest_group_manager.h"
#include "content/public/test/browser_task_environment.h"
#include "net/base/schemeful_site.h"
#include "net/first_party_sets/first_party_set_entry.h"
@@ -136,39 +135,6 @@
raw_ptr<PrivacySandboxService> service_;
};
-class TestInterestGroupManager : public content::InterestGroupManager {
- public:
- void SetInterestGroupDataKeys(
- const std::vector<InterestGroupDataKey>& data_keys) {
- data_keys_ = data_keys;
- }
-
- // content::InterestGroupManager:
- void GetAllInterestGroupJoiningOrigins(
- base::OnceCallback<void(std::vector<url::Origin>)> callback) override {
- NOTREACHED();
- }
- void GetAllInterestGroupDataKeys(
- base::OnceCallback<void(std::vector<InterestGroupDataKey>)> callback)
- override {
- std::move(callback).Run(data_keys_);
- }
- void RemoveInterestGroupsByDataKey(InterestGroupDataKey data_key,
- base::OnceClosure callback) override {
- NOTREACHED();
- }
- void AddTrustedServerKeysDebugOverride(
- TrustedServerAPIType api,
- const url::Origin& coordinator,
- std::string serialized_keys,
- base::OnceCallback<void(std::optional<std::string>)> callback) override {
- NOTREACHED();
- }
-
- private:
- std::vector<InterestGroupDataKey> data_keys_;
-};
-
// Remove any user preference settings for Related Website Set related
// preferences, returning them to their default value.
void ClearRwsUserPrefs(
@@ -441,9 +407,6 @@
content_settings::CookieSettings* cookie_settings() {
return CookieSettingsFactory::GetForProfile(profile()).get();
}
- TestInterestGroupManager* test_interest_group_manager() {
- return &test_interest_group_manager_;
- }
content::BrowsingDataRemover* browsing_data_remover() {
return profile()->GetBrowsingDataRemover();
}
@@ -495,10 +458,9 @@
content::BrowserContext* context) {
return std::make_unique<PrivacySandboxServiceImpl>(
profile(), privacy_sandbox_settings(), cookie_settings(),
- profile()->GetPrefs(), test_interest_group_manager(), GetProfileType(),
- browsing_data_remover(), host_content_settings_map(),
- mock_browsing_topics_service(), first_party_sets_policy_service(),
- mock_privacy_sandbox_countries());
+ profile()->GetPrefs(), GetProfileType(), browsing_data_remover(),
+ host_content_settings_map(), mock_browsing_topics_service(),
+ first_party_sets_policy_service(), mock_privacy_sandbox_countries());
}
content::BrowserTaskEnvironment browser_task_environment_;
@@ -514,7 +476,6 @@
base::test::ScopedFeatureList outer_feature_list_;
base::test::ScopedFeatureList inner_feature_list_;
- TestInterestGroupManager test_interest_group_manager_;
browsing_topics::MockBrowsingTopicsService mock_browsing_topics_service_;
first_party_sets::ScopedMockFirstPartySetsHandler
@@ -662,98 +623,6 @@
ASSERT_EQ(should_use_china_domain, false);
}
-TEST_F(PrivacySandboxServiceTest, GetFledgeJoiningEtldPlusOne) {
- // Confirm that the set of FLEDGE origins which were top-frame for FLEDGE join
- // actions is correctly converted into a list of eTLD+1s.
-
- using FledgeTestCase =
- std::pair<std::vector<url::Origin>, std::vector<std::string>>;
-
- // Items which map to the same eTLD+1 should be coalesced into a single entry.
- FledgeTestCase test_case_1 = {
- {url::Origin::Create(GURL("https://www.example.com")),
- url::Origin::Create(GURL("https://example.com:8080")),
- url::Origin::Create(GURL("http://www.example.com"))},
- {"example.com"}};
-
- // eTLD's should return the host instead, this is relevant for sites which
- // are themselves on the PSL, e.g. github.io.
- FledgeTestCase test_case_2 = {
- {
- url::Origin::Create(GURL("https://co.uk")),
- url::Origin::Create(GURL("http://co.uk")),
- url::Origin::Create(GURL("http://example.co.uk")),
- },
- {"co.uk", "example.co.uk"}};
-
- // IP addresses should also return the host.
- FledgeTestCase test_case_3 = {
- {
- url::Origin::Create(GURL("https://192.168.1.2")),
- url::Origin::Create(GURL("https://192.168.1.2:8080")),
- url::Origin::Create(GURL("https://192.168.1.3:8080")),
- },
- {"192.168.1.2", "192.168.1.3"}};
-
- // Results should be alphabetically ordered.
- FledgeTestCase test_case_4 = {{
- url::Origin::Create(GURL("https://d.com")),
- url::Origin::Create(GURL("https://b.com")),
- url::Origin::Create(GURL("https://a.com")),
- url::Origin::Create(GURL("https://c.com")),
- },
- {"a.com", "b.com", "c.com", "d.com"}};
-
- std::vector<FledgeTestCase> test_cases = {test_case_1, test_case_2,
- test_case_3, test_case_4};
-
- for (const auto& [origins, expected] : test_cases) {
- base::HistogramTester histogram_tester;
- test_interest_group_manager()->SetInterestGroupDataKeys(
- base::ToVector(origins, [](const auto& origin) {
- return content::InterestGroupManager::InterestGroupDataKey{
- url::Origin::Create(GURL("https://embedded.com")), origin};
- }));
-
- bool callback_called = false;
- auto callback = base::BindLambdaForTesting(
- [&](std::vector<std::string> items_for_display) {
- ASSERT_EQ(items_for_display.size(), expected.size());
- for (size_t i = 0; i < items_for_display.size(); i++) {
- EXPECT_EQ(expected[i], items_for_display[i]);
- }
- callback_called = true;
- });
-
- privacy_sandbox_service()->GetFledgeJoiningEtldPlusOneForDisplay(callback);
- EXPECT_TRUE(callback_called);
- histogram_tester.ExpectUniqueSample(
- "PrivacySandbox.ProtectedAudience.JoiningTopFrameDisplayed", true,
- origins.size());
- }
-}
-
-TEST_F(PrivacySandboxServiceTest, GetFledgeJoiningEtldPlusOne_InvalidTopFrame) {
- // Confirm that when an invalid top frame is received, the appropriate metric
- // is recorded, and the returned list is empty.
- base::HistogramTester histogram_tester;
- auto missing_top_frame = content::InterestGroupManager::InterestGroupDataKey{
- url::Origin::Create(GURL("https://embedded.com")), url::Origin()};
- test_interest_group_manager()->SetInterestGroupDataKeys({missing_top_frame});
-
- bool callback_called = false;
- auto callback = base::BindLambdaForTesting(
- [&](std::vector<std::string> items_for_display) {
- ASSERT_EQ(items_for_display.size(), 0u);
- callback_called = true;
- });
-
- privacy_sandbox_service()->GetFledgeJoiningEtldPlusOneForDisplay(callback);
- EXPECT_TRUE(callback_called);
- histogram_tester.ExpectUniqueSample(
- "PrivacySandbox.ProtectedAudience.JoiningTopFrameDisplayed", false, 1);
-}
-
TEST_F(PrivacySandboxServiceTest, GetFledgeBlockedEtldPlusOne) {
// Confirm that blocked FLEDGE top frame eTLD+1's are correctly produced
// for display.
diff --git a/components/browsing_data/content/browsing_data_model_unittest.cc b/components/browsing_data/content/browsing_data_model_unittest.cc
index cd6b47d..94ef257c 100644
--- a/components/browsing_data/content/browsing_data_model_unittest.cc
+++ b/components/browsing_data/content/browsing_data_model_unittest.cc
@@ -588,8 +588,6 @@
auto partitioned_shared_dictionary_key = net::SharedDictionaryIsolationKey{
kSiteOrigin, net::SchemefulSite(kTestOrigin)};
- content::InterestGroupManager::InterestGroupDataKey interest_group_key{
- kSiteOrigin, kSiteOrigin};
net::device_bound_sessions::SessionKey device_bound_session_key(
net::SchemefulSite(kSiteOrigin.GetURL()),
net::device_bound_sessions::SessionKey::Id("session_id"));
@@ -626,7 +624,6 @@
partitioned_shared_worker_info},
{BrowsingDataModel::StorageType::kCookie, *partitioned_cookie},
{BrowsingDataModel::StorageType::kTrustTokens, kSiteOrigin},
- {BrowsingDataModel::StorageType::kInterestGroup, interest_group_key},
{BrowsingDataModel::StorageType::kSharedDictionary,
partitioned_shared_dictionary_key}};
diff --git a/components/privacy_sandbox/privacy_sandbox_test_util_unittest.cc b/components/privacy_sandbox/privacy_sandbox_test_util_unittest.cc
index 815f8d8..fde869c7 100644
--- a/components/privacy_sandbox/privacy_sandbox_test_util_unittest.cc
+++ b/components/privacy_sandbox/privacy_sandbox_test_util_unittest.cc
... (truncated)
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