Skip to content

Commit

Permalink
Merge pull request #9073 from brave/pr9053_csp-shields-control_1.25.x
Browse files Browse the repository at this point in the history
Tie CSP rule injection to Shields ads/tracker setting (uplift to 1.25.x)
  • Loading branch information
kjozwiak authored Jun 10, 2021
2 parents f1dc0fd + abea753 commit 06e2821
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 17 deletions.
54 changes: 42 additions & 12 deletions browser/brave_shields/ad_block_service_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,10 @@ void AdBlockServiceTest::WaitForBraveExtensionShieldsDataReady() {
ASSERT_TRUE(extension_listener.WaitUntilSatisfied());
}

void AdBlockServiceTest::ShieldsDown(const GURL& url) {
brave_shields::SetBraveShieldsEnabled(content_settings(), false, url);
}

// Load a page with an ad image, and make sure it is blocked.
IN_PROC_BROWSER_TEST_F(AdBlockServiceTest, AdsGetBlockedByDefaultBlocker) {
ASSERT_TRUE(InstallDefaultAdBlockExtension());
Expand Down Expand Up @@ -798,12 +802,12 @@ IN_PROC_BROWSER_TEST_F(AdBlockServiceTest, CspRule) {
browser()->tab_strip_model()->GetActiveWebContents();

auto res = EvalJs(contents, "await window.allLoaded");
ASSERT_EQ(true, EvalJs(contents, "!!window.loadedNonceScript"));
ASSERT_EQ(true, EvalJs(contents, "!!window.loadedEvalScript"));
ASSERT_EQ(true, EvalJs(contents, "!!window.loadedSamePartyScript"));
ASSERT_EQ(false, EvalJs(contents, "!!window.loadedThirdPartyScript"));
ASSERT_EQ(false, EvalJs(contents, "!!window.loadedUnsafeInlineScript"));
ASSERT_EQ(true, EvalJs(contents, "!!window.loadedDataImage"));
EXPECT_EQ(true, EvalJs(contents, "!!window.loadedNonceScript"));
EXPECT_EQ(true, EvalJs(contents, "!!window.loadedEvalScript"));
EXPECT_EQ(true, EvalJs(contents, "!!window.loadedSamePartyScript"));
EXPECT_EQ(false, EvalJs(contents, "!!window.loadedThirdPartyScript"));
EXPECT_EQ(false, EvalJs(contents, "!!window.loadedUnsafeInlineScript"));
EXPECT_EQ(true, EvalJs(contents, "!!window.loadedDataImage"));

// Violations of injected CSP directives do not increment the Shields counter
EXPECT_EQ(browser()->profile()->GetPrefs()->GetUint64(kAdsBlocked), 0ULL);
Expand Down Expand Up @@ -831,17 +835,43 @@ IN_PROC_BROWSER_TEST_F(AdBlockServiceTest, CspRuleMerging) {
browser()->tab_strip_model()->GetActiveWebContents();

auto res = EvalJs(contents, "await window.allLoaded");
ASSERT_EQ(true, EvalJs(contents, "!!window.loadedNonceScript"));
ASSERT_EQ(true, EvalJs(contents, "!!window.loadedEvalScript"));
ASSERT_EQ(false, EvalJs(contents, "!!window.loadedSamePartyScript"));
ASSERT_EQ(false, EvalJs(contents, "!!window.loadedThirdPartyScript"));
ASSERT_EQ(false, EvalJs(contents, "!!window.loadedUnsafeInlineScript"));
ASSERT_EQ(false, EvalJs(contents, "!!window.loadedDataImage"));
EXPECT_EQ(true, EvalJs(contents, "!!window.loadedNonceScript"));
EXPECT_EQ(true, EvalJs(contents, "!!window.loadedEvalScript"));
EXPECT_EQ(false, EvalJs(contents, "!!window.loadedSamePartyScript"));
EXPECT_EQ(false, EvalJs(contents, "!!window.loadedThirdPartyScript"));
EXPECT_EQ(false, EvalJs(contents, "!!window.loadedUnsafeInlineScript"));
EXPECT_EQ(false, EvalJs(contents, "!!window.loadedDataImage"));

// Violations of injected CSP directives do not increment the Shields counter
EXPECT_EQ(browser()->profile()->GetPrefs()->GetUint64(kAdsBlocked), 0ULL);
}

// Verify that scripts violating a Content Security Policy from a `$csp` rule
// are not loaded.
IN_PROC_BROWSER_TEST_F(AdBlockServiceTest, CspRuleShieldsDown) {
UpdateAdBlockInstanceWithRules(
"||example.com^$csp=script-src 'nonce-abcdef' 'unsafe-eval' 'self'");
EXPECT_EQ(browser()->profile()->GetPrefs()->GetUint64(kAdsBlocked), 0ULL);

const GURL url =
embedded_test_server()->GetURL("example.com", "/csp_rules.html");
ShieldsDown(url);

ui_test_utils::NavigateToURL(browser(), url);
content::WebContents* contents =
browser()->tab_strip_model()->GetActiveWebContents();

auto res = EvalJs(contents, "await window.allLoaded");
EXPECT_EQ(true, EvalJs(contents, "!!window.loadedNonceScript"));
EXPECT_EQ(true, EvalJs(contents, "!!window.loadedEvalScript"));
EXPECT_EQ(true, EvalJs(contents, "!!window.loadedSamePartyScript"));
EXPECT_EQ(true, EvalJs(contents, "!!window.loadedThirdPartyScript"));
EXPECT_EQ(true, EvalJs(contents, "!!window.loadedUnsafeInlineScript"));
EXPECT_EQ(true, EvalJs(contents, "!!window.loadedDataImage"));

EXPECT_EQ(browser()->profile()->GetPrefs()->GetUint64(kAdsBlocked), 0ULL);
}

class CosmeticFilteringFlagDisabledTest : public AdBlockServiceTest {
public:
CosmeticFilteringFlagDisabledTest() {
Expand Down
1 change: 1 addition & 0 deletions browser/brave_shields/ad_block_service_browsertest.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class AdBlockServiceTest : public extensions::ExtensionBrowserTest {
bool StartAdBlockRegionalServices();
void WaitForAdBlockServiceThreads();
void WaitForBraveExtensionShieldsDataReady();
void ShieldsDown(const GURL& url);
};

#endif // BRAVE_BROWSER_BRAVE_SHIELDS_AD_BLOCK_SERVICE_BROWSERTEST_H_
9 changes: 5 additions & 4 deletions browser/net/brave_ad_block_csp_network_delegate_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ base::Optional<std::string> GetCspDirectivesOnTaskRunner(
std::shared_ptr<BraveRequestInfo> ctx,
base::Optional<std::string> original_csp) {
std::string source_host;
if (ctx->initiator_url.is_valid()) {
if (ctx->initiator_url.is_valid() && !ctx->initiator_url.host().empty()) {
source_host = ctx->initiator_url.host();
} else if (ctx->request_url.is_valid()) {
// Top-level document requests do not have a valid initiator URL, so we use
// the request URL as the initiator.
// Top-level document requests do not have a valid initiator URL, and
// requests from special schemes like file:// do not have host parts, so we
// use the request URL as the initiator.
source_host = ctx->request_url.host();
} else {
return base::nullopt;
Expand Down Expand Up @@ -62,7 +63,7 @@ int OnHeadersReceived_AdBlockCspWork(
std::shared_ptr<brave::BraveRequestInfo> ctx) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

if (!response_headers) {
if (!response_headers || !ctx->allow_brave_shields || ctx->allow_ads) {
return net::OK;
}

Expand Down
3 changes: 3 additions & 0 deletions test/data/adbanner.js.mock-http-headers
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
HTTP/1.1 200 OK
Content-Type: application/javascript
Access-Control-Allow-Origin: *
2 changes: 1 addition & 1 deletion test/data/csp_rules.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

const thirdPartyScriptPromise = new Promise(resolve => {
const thirdPartyScript = document.createElement('script');
thirdPartyScript.src = 'https://thirdparty.com/adbanner.js';
thirdPartyScript.src = '/cross-site/thirdparty.com/adbanner.js';
thirdPartyScript.onload = (r) => {
window.loadedThirdPartyScript = true;
resolve();
Expand Down

0 comments on commit 06e2821

Please sign in to comment.