Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent storage partitioning bypass with a trial when Shields active. #27042

Merged
merged 1 commit into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions browser/brave_content_browser_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
#include "chrome/browser/chrome_browser_interface_binders.h"
#include "chrome/browser/chrome_browser_main.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/content_settings/cookie_settings_factory.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_io_data.h"
Expand Down Expand Up @@ -689,6 +690,27 @@ BraveContentBrowserClient::GetEphemeralStorageToken(
return es_tab_helper->GetEphemeralStorageToken(origin);
}

bool BraveContentBrowserClient::CanThirdPartyStoragePartitioningBeDisabled(
content::BrowserContext* browser_context,
const url::Origin& origin) {
auto* host_content_settings_map =
HostContentSettingsMapFactory::GetForProfile(browser_context);
if (!host_content_settings_map) {
return false;
}
auto cookie_settings = CookieSettingsFactory::GetForProfile(
Profile::FromBrowserContext(browser_context));
if (!cookie_settings) {
return false;
}
const auto url = origin.GetURL();
return !brave_shields::GetBraveShieldsEnabled(host_content_settings_map,
url) ||
brave_shields::GetCookieControlType(host_content_settings_map,
cookie_settings.get(), url) ==
brave_shields::ControlType::ALLOW;
}

bool BraveContentBrowserClient::AllowWorkerFingerprinting(
const GURL& url,
content::BrowserContext* browser_context) {
Expand Down
4 changes: 4 additions & 0 deletions browser/brave_content_browser_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ class BraveContentBrowserClient : public ChromeContentBrowserClient {
content::RenderFrameHost* render_frame_host,
const url::Origin& origin) override;

bool CanThirdPartyStoragePartitioningBeDisabled(
content::BrowserContext* browser_context,
const url::Origin& origin) override;

bool AllowWorkerFingerprinting(
const GURL& url,
content::BrowserContext* browser_context) override;
Expand Down
124 changes: 124 additions & 0 deletions browser/ephemeral_storage/ephemeral_storage_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,15 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_enums.h"
#include "chrome/test/base/chrome_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
Expand Down Expand Up @@ -1277,3 +1280,124 @@ IN_PROC_BROWSER_TEST_F(
EXPECT_EQ("", values_after.iframe_1.cookies);
EXPECT_EQ("", values_after.iframe_2.cookies);
}

class EphemeralStorageWithDisableThirdPartyStoragePartitioningBrowserTest
: public EphemeralStorageBrowserTest,
public content::WebContentsObserver,
public testing::WithParamInterface<bool> {
public:
EphemeralStorageWithDisableThirdPartyStoragePartitioningBrowserTest() {}

void ReadyToCommitNavigation(
content::NavigationHandle* navigation_handle) override {
if (!navigation_handle->IsInPrimaryMainFrame()) {
return;
}

blink::RuntimeFeatureStateContext& context =
navigation_handle->GetMutableRuntimeFeatureStateContext();
context.SetDisableThirdPartyStoragePartitioning2Enabled(GetParam());
}
};

IN_PROC_BROWSER_TEST_P(
EphemeralStorageWithDisableThirdPartyStoragePartitioningBrowserTest,
StorageIsPartitionedWithShieldsEnabled) {
auto* web_contents = chrome_test_utils::GetActiveWebContents(this);
Observe(web_contents);
ASSERT_TRUE(
brave_shields::GetBraveShieldsEnabled(content_settings(), GURL()));

ASSERT_TRUE(
ui_test_utils::NavigateToURL(browser(), a_site_ephemeral_storage_url_));

// The page this tab is loaded via a.com and has two b.com third-party
// iframes. The third-party iframes should be partitioned.
SetValuesInFrames(web_contents, "a.com", "from=a.com");
ValuesFromFrames third_party_values = GetValuesFromFrames(web_contents);
EXPECT_EQ("a.com", third_party_values.main_frame.local_storage);
EXPECT_EQ("a.com", third_party_values.iframe_1.local_storage);
EXPECT_EQ("a.com", third_party_values.iframe_2.local_storage);

EXPECT_EQ("a.com", third_party_values.main_frame.session_storage);
EXPECT_EQ("a.com", third_party_values.iframe_1.session_storage);
EXPECT_EQ("a.com", third_party_values.iframe_2.session_storage);

EXPECT_EQ("from=a.com", third_party_values.main_frame.cookies);
EXPECT_EQ("from=a.com", third_party_values.iframe_1.cookies);
EXPECT_EQ("from=a.com", third_party_values.iframe_2.cookies);

ASSERT_TRUE(
ui_test_utils::NavigateToURL(browser(), b_site_ephemeral_storage_url_));

// The storage in the first-party iframes should reflect empty values not
// altered by a.com site.
ValuesFromFrames first_party_values = GetValuesFromFrames(web_contents);
ExpectValuesFromFramesAreEmpty(FROM_HERE, first_party_values);
}

IN_PROC_BROWSER_TEST_P(
EphemeralStorageWithDisableThirdPartyStoragePartitioningBrowserTest,
StorageIsPartitionedWithShieldsDisabled) {
auto* web_contents = chrome_test_utils::GetActiveWebContents(this);
Observe(chrome_test_utils::GetActiveWebContents(this));
brave_shields::SetBraveShieldsEnabled(content_settings(), false,
a_site_ephemeral_storage_url_);
brave_shields::SetBraveShieldsEnabled(content_settings(), false,
b_site_ephemeral_storage_url_);
brave_shields::SetBraveShieldsEnabled(content_settings(), false,
c_site_ephemeral_storage_url_);

ASSERT_TRUE(
ui_test_utils::NavigateToURL(browser(), a_site_ephemeral_storage_url_));

// The page this tab is loaded via a.com and has two b.com third-party
// iframes. The third-party iframes should be partitioned.
SetValuesInFrames(web_contents, "a.com", "from=a.com");
ValuesFromFrames third_party_values = GetValuesFromFrames(web_contents);
EXPECT_EQ("a.com", third_party_values.main_frame.local_storage);
EXPECT_EQ("a.com", third_party_values.iframe_1.local_storage);
EXPECT_EQ("a.com", third_party_values.iframe_2.local_storage);

EXPECT_EQ("a.com", third_party_values.main_frame.session_storage);
EXPECT_EQ("a.com", third_party_values.iframe_1.session_storage);
EXPECT_EQ("a.com", third_party_values.iframe_2.session_storage);

EXPECT_EQ("from=a.com", third_party_values.main_frame.cookies);
EXPECT_EQ("from=a.com", third_party_values.iframe_1.cookies);
EXPECT_EQ("from=a.com", third_party_values.iframe_2.cookies);

ASSERT_TRUE(
ui_test_utils::NavigateToURL(browser(), b_site_ephemeral_storage_url_));

ValuesFromFrames first_party_values = GetValuesFromFrames(web_contents);
if (GetParam()) {
// If origin trial is enabled, the storage should not be partitioned.
EXPECT_EQ("a.com", first_party_values.main_frame.local_storage);
EXPECT_EQ("a.com", first_party_values.iframe_1.local_storage);
EXPECT_EQ("a.com", first_party_values.iframe_2.local_storage);

EXPECT_EQ("a.com", first_party_values.main_frame.session_storage);
EXPECT_EQ("a.com", first_party_values.iframe_1.session_storage);
EXPECT_EQ("a.com", first_party_values.iframe_2.session_storage);
} else {
// If origin trial is disabled, the storage should be partitioned.
EXPECT_EQ(nullptr, first_party_values.main_frame.local_storage);
EXPECT_EQ(nullptr, first_party_values.iframe_1.local_storage);
EXPECT_EQ(nullptr, first_party_values.iframe_2.local_storage);

EXPECT_EQ(nullptr, first_party_values.main_frame.session_storage);
EXPECT_EQ(nullptr, first_party_values.iframe_1.session_storage);
EXPECT_EQ(nullptr, first_party_values.iframe_2.session_storage);
}

// Cookies are not partitioned if shields are disabled.
EXPECT_EQ("from=a.com", first_party_values.main_frame.cookies);
EXPECT_EQ("from=a.com", first_party_values.iframe_1.cookies);
EXPECT_EQ("from=a.com", first_party_values.iframe_2.cookies);
}

INSTANTIATE_TEST_SUITE_P(
,
EphemeralStorageWithDisableThirdPartyStoragePartitioningBrowserTest,
testing::Bool());
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,18 @@
return *ephemeral_storage_token; \
}

#define BRAVE_RENDER_FRAME_HOST_IMPL_IS_THIRD_PARTY_STORAGE_PARTITIONING_ENABLED_CHECK_IF_CAN_BE_DISABLED \
if (GetContentClient() \
->browser() \
->CanThirdPartyStoragePartitioningBeDisabled( \
GetBrowserContext(), \
main_frame_for_storage_partitioning->GetLastCommittedOrigin()))

#include "src/content/browser/renderer_host/render_frame_host_impl.cc"

#undef BRAVE_RENDER_FRAME_HOST_IMPL_COMPUTE_ISOLATION_INFO_INTERNAL
#undef BRAVE_RENDER_FRAME_HOST_IMPL_COMPUTE_NONCE
#undef BRAVE_RENDER_FRAME_HOST_IMPL_IS_THIRD_PARTY_STORAGE_PARTITIONING_ENABLED_CHECK_IF_CAN_BE_DISABLED

namespace content {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ ContentBrowserClient::GetEphemeralStorageToken(
return std::nullopt;
}

bool ContentBrowserClient::CanThirdPartyStoragePartitioningBeDisabled(
BrowserContext* browser_context,
const url::Origin& origin) {
return false;
}

brave_shields::mojom::ShieldsSettingsPtr
ContentBrowserClient::WorkerGetBraveShieldSettings(
const GURL& url,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
const GURL& url); \
virtual std::optional<base::UnguessableToken> GetEphemeralStorageToken( \
RenderFrameHost* render_frame_host, const url::Origin& origin); \
virtual bool CanThirdPartyStoragePartitioningBeDisabled( \
BrowserContext* browser_context, const url::Origin& origin); \
virtual bool AllowWorkerFingerprinting(const GURL& url, \
BrowserContext* browser_context); \
virtual brave_shields::mojom::ShieldsSettingsPtr \
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index f58b9b0333e01f95ecf1b1d3fd3e273b675705cc..0d8c54fa8dcf8052f9c6d6a28cd5d0395688ec1e 100644
index f58b9b0333e01f95ecf1b1d3fd3e273b675705cc..e14627f84f7dab5f368e36dbc30d8fbeb87409df 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -4820,6 +4820,7 @@ net::IsolationInfo RenderFrameHostImpl::ComputeIsolationInfoInternal(
Expand All @@ -18,7 +18,23 @@ index f58b9b0333e01f95ecf1b1d3fd3e273b675705cc..0d8c54fa8dcf8052f9c6d6a28cd5d039
// If it's a credentialless frame tree, use its nonce even if it's within a
// fenced frame tree to maintain the guarantee that a credentialless frame
// tree has a unique nonce.
@@ -9236,6 +9238,7 @@ void RenderFrameHostImpl::CreateNewWindow(
@@ -4872,6 +4874,7 @@ bool RenderFrameHostImpl::IsThirdPartyStoragePartitioningEnabled(
// current value of net::features::ThirdPartyStoragePartitioning.
if (rfs_document_data_for_storage_key->runtime_feature_state_read_context()
.IsDisableThirdPartyStoragePartitioning2Enabled()) {
+ BRAVE_RENDER_FRAME_HOST_IMPL_IS_THIRD_PARTY_STORAGE_PARTITIONING_ENABLED_CHECK_IF_CAN_BE_DISABLED
return false;
}
// Compile the list of third-party origins we need to check in addition to
@@ -4889,6 +4892,7 @@ bool RenderFrameHostImpl::IsThirdPartyStoragePartitioningEnabled(
if (rfs_document_data_for_storage_key->runtime_feature_state_read_context()
.IsDisableThirdPartyStoragePartitioning2EnabledForThirdParty(
third_party_origins)) {
+ BRAVE_RENDER_FRAME_HOST_IMPL_IS_THIRD_PARTY_STORAGE_PARTITIONING_ENABLED_CHECK_IF_CAN_BE_DISABLED
return false;
}
} else {
@@ -9236,6 +9240,7 @@ void RenderFrameHostImpl::CreateNewWindow(
dom_storage_context, params->session_storage_namespace_id);
}

Expand Down
Loading