Commit e832c8fa authored by Karandeep Bhatia's avatar Karandeep Bhatia Committed by Commit Bot

IsolatedWorldCSP: Add tests for remotely hosted code.

Add tests for remotely hosted code in isolated worlds for Mv2 and Mv3
extensions. This tests that operations in an isolated world which
execute remotely hosted code are prohibited using a strict CSP.

BUG=896041

Change-Id: Iec0433d023445adf27d463b5f259d6a2b63196e7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2451501
Auto-Submit: Karan Bhatia <karandeepb@chromium.org>
Commit-Queue: Karan Bhatia <karandeepb@chromium.org>
Reviewed-by: default avatarDevlin <rdevlin.cronin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#816378}
parent 60163599
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "net/dns/mock_host_resolver.h"
namespace extensions {
class IsolatedWorldCspBrowserTest : public ExtensionApiTest {
public:
// ExtensionApiTest override.
void SetUpOnMainThread() override {
extensions::ExtensionApiTest::SetUpOnMainThread();
// Override the path used for loading the extension.
test_data_dir_ = test_data_dir_.AppendASCII("isolated_world_csp");
embedded_test_server()->ServeFilesFromDirectory(test_data_dir_);
ASSERT_TRUE(StartEmbeddedTestServer());
// Map all hosts to localhost.
host_resolver()->AddRule("*", "127.0.0.1");
}
};
// Test that a Manifest V2 content script can use eval by bypassing the main
// world CSP.
IN_PROC_BROWSER_TEST_F(IsolatedWorldCspBrowserTest, Eval_ManifestV2) {
GURL url = embedded_test_server()->GetURL("eval.com",
"/page_with_script_src_csp.html");
ASSERT_TRUE(RunExtensionSubtest("mv2", url.spec())) << message_;
}
// Test that a Manifest V3 content script can't use eval.
IN_PROC_BROWSER_TEST_F(IsolatedWorldCspBrowserTest, Eval_ManifestV3) {
// TODO(crbug.com/896897): Ignore manifest warnings for now since we get a
// warning for using manifest version 3.
GURL url = embedded_test_server()->GetURL("eval.com",
"/page_with_script_src_csp.html");
ASSERT_TRUE(RunExtensionSubtest("mv3", url.spec(),
kFlagIgnoreManifestWarnings, kFlagNone))
<< message_;
}
// Test that a Manifest V2 content script can navigate to a javascript url by
// bypassing the main world CSP.
IN_PROC_BROWSER_TEST_F(IsolatedWorldCspBrowserTest, JavascriptUrl_ManifestV2) {
GURL url = embedded_test_server()->GetURL("js-url.com",
"/page_with_script_src_csp.html");
ASSERT_TRUE(RunExtensionSubtest("mv2", url.spec())) << message_;
}
// Test that a Manifest V3 content script can't navigate to a javascript url
// while in its isolated world.
IN_PROC_BROWSER_TEST_F(IsolatedWorldCspBrowserTest, JavascriptUrl_ManifestV3) {
// We wait on a console message which will be raised on an unsuccessful
// navigation to a javascript url since there isn't any other clean way to
// assert that the navigation didn't succeed.
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
content::WebContentsConsoleObserver console_observer(web_contents);
console_observer.SetPattern(
"Refused to run the JavaScript URL because it violates the following "
"Content Security Policy directive: \"script-src 'self'\".*");
// TODO(crbug.com/896897): Ignore manifest warnings for now since we get a
// warning for using manifest version 3.
GURL url = embedded_test_server()->GetURL("js-url.com",
"/page_with_script_src_csp.html");
ASSERT_TRUE(RunExtensionSubtest("mv3", url.spec(),
kFlagIgnoreManifestWarnings, kFlagNone))
<< message_;
console_observer.Wait();
// Also ensure the page title wasn't changed.
EXPECT_EQ(base::ASCIIToUTF16("Page With CSP"), web_contents->GetTitle());
}
// Test that a Manifest V2 content script can execute a remote script even if
// it is disallowed by the main world CSP.
IN_PROC_BROWSER_TEST_F(IsolatedWorldCspBrowserTest,
RemoteScriptSrc_ManifestV2) {
GURL url = embedded_test_server()->GetURL("remote-script.com",
"/page_with_script_src_csp.html");
ASSERT_TRUE(RunExtensionSubtest("mv2", url.spec())) << message_;
}
// Test that a Manifest V3 content script can't execute a remote script even if
// is allowed by the main world CSP.
IN_PROC_BROWSER_TEST_F(IsolatedWorldCspBrowserTest,
RemoteScriptSrc_ManifestV3) {
// TODO(crbug.com/896897): Ignore manifest warnings for now since we get a
// warning for using manifest version 3.
GURL url = embedded_test_server()->GetURL("remote-script.com",
"/page_with_script_src_csp.html");
ASSERT_TRUE(RunExtensionSubtest("mv3", url.spec(),
kFlagIgnoreManifestWarnings, kFlagNone))
<< message_;
}
} // namespace extensions
......@@ -2006,6 +2006,7 @@ if (!is_android) {
"../browser/extensions/identifiability_metrics_test_util.cc",
"../browser/extensions/identifiability_metrics_test_util.h",
"../browser/extensions/isolated_app_browsertest.cc",
"../browser/extensions/isolated_world_csp_browsertest.cc",
"../browser/extensions/lazy_background_page_apitest.cc",
"../browser/extensions/lazy_background_page_test_util.h",
"../browser/extensions/manifest_v3_browsertest.cc",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
chrome.test.runTests([function testEval() {
window.foo = 2;
eval('window.foo = 3;');
chrome.test.assertEq(3, window.foo);
chrome.test.succeed();
}]);
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
const button = document.createElement('button');
button.id = 'my-button';
// DOM Property event handlers execute in the world they are registered in.
button.onclick = () => {
chrome.test.notifyPass();
};
document.body.appendChild(button);
location.href = 'javascript:document.getElementById("my-button").click();';
{
"name": "MV2: Bypass main world CSP in isolated worlds.",
"manifest_version": 2,
"version": "1.0",
"content_scripts": [
{
"matches": ["*://eval.com/*"],
"js": ["eval.js"]
},
{
"matches": ["*://js-url.com/*"],
"js": ["javascript_url.js"]
},
{
"matches": ["*://remote-script.com/*"],
"js": ["remote_script.js"]
}
]
}
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
chrome.test.getConfig(config => {
chrome.test.runTests([function testRemoteScript() {
let port = config.testServer.port;
let script = document.createElement('script');
script.src = `http://google.com:${port}/script.js`;
script.onload = () => {
chrome.test.assertEq('New Title', document.title);
chrome.test.succeed();
};
script.onerror = () => {
chrome.test.fail('Script load failed unexpectedly');
};
document.body.appendChild(script);
}]);
});
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
chrome.test.runTests([function testEval() {
window.foo = 2;
var exceptedExceptionMessage = 'Refused to evaluate a string as JavaScript ' +
'because \'unsafe-eval\' is not an allowed source of script in the ' +
'following Content Security Policy directive: "script-src \'self\'"';
chrome.test.assertThrows(
eval, ['window.foo = 3;'], new RegExp(exceptedExceptionMessage));
chrome.test.assertEq(2, window.foo);
chrome.test.succeed();
}]);
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
location.href = 'javascript:document.title="New Title";';
chrome.test.notifyPass();
{
"name": "MV3: Strict isolated world CSP.",
"manifest_version": 3,
"version": "1.0",
"content_scripts": [
{
"matches": ["*://eval.com/*"],
"js": ["eval.js"]
},
{
"matches": ["*://js-url.com/*"],
"js": ["javascript_url.js"]
},
{
"matches": ["*://remote-script.com/*"],
"js": ["remote_script.js"]
}
]
}
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
chrome.test.getConfig(config => {
let port = config.testServer.port;
let script = document.createElement('script');
script.src = `http://example.com:${port}/script.js`;
script.onload = () => {
chrome.test.notifyFail('Script load succeeded unexpectedly');
};
script.onerror = () => {
chrome.test.notifyPass();
};
document.body.appendChild(script);
});
<!DOCTYPE html>
<meta http-equiv="Content-Security-Policy" content="script-src http://example.com:*;">
<title>Page With CSP</title>
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
document.title = 'New Title';
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment