Commit acd8a467 authored by Eriko Kurimoto's avatar Eriko Kurimoto Committed by Commit Bot

SharedWorker: Use CSP headers to outside settings

This CL passes real ContentSecurityPolicy and ContentSecurityPolicyType
values to creation_params which are used for SharedWorker scripts fetching.

By this change, outsideSettings CSP is applied to scripts statically
imported from module SharedWorker top-level scripts.
This behavior is tested in the static import section in the added test.
(Previously the CSP was not applied at all for such scripts,
but it's OK because module SharedWorker is not yet shipped.)

This CL doesn't affect the behavior of classic SharedWorker and
dynamic imports (either from module or classic SharedWorker).

Web-platform-tests to check its behavior on Module SharedWorker are added.
WPTs for Classic SharedWorker will be added in the following CLs.

Bug: 1049011, 824646
Change-Id: I6fa79b0394426f09b19da1abbdf9ecf483d558ec
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2038297
Commit-Queue: Eriko Kurimoto <elkurin@google.com>
Reviewed-by: default avatarHiroshige Hayashizaki <hiroshige@chromium.org>
Reviewed-by: default avatarHiroki Nakagawa <nhiroki@chromium.org>
Cr-Commit-Position: refs/heads/master@{#740538}
parent 0dbd6e76
......@@ -216,13 +216,18 @@ void WebSharedWorkerImpl::StartWorkerContext(
false /* strictly_block_blockable_mixed_content */,
GenericFontFamilySettings());
// Some params (e.g., referrer policy, address space, CSP) passed to
// GlobalScopeCreationParams are dummy values. They will be updated after
// worker script fetch on the worker thread.
// CSP headers for parent Window's CSP.
Vector<CSPHeaderAndType> outside_csp_headers;
outside_csp_headers.ReserveInitialCapacity(1);
outside_csp_headers.UncheckedAppend(
CSPHeaderAndType(content_security_policy, policy_type));
// Some params (e.g. address space) passed to GlobalScopeCreationParams are
// dummy values. They will be updated after worker script fetch on the worker
// thread.
auto creation_params = std::make_unique<GlobalScopeCreationParams>(
script_request_url, script_type,
OffMainThreadWorkerScriptFetchOption::kEnabled, name, user_agent,
std::move(web_worker_fetch_context), Vector<CSPHeaderAndType>(),
std::move(web_worker_fetch_context), outside_csp_headers,
outside_settings_object->GetReferrerPolicy(),
outside_settings_object->GetSecurityOrigin(), starter_secure_context,
outside_settings_object->GetHttpsState(),
......
// Import a remote origin script.
import('https://{{domains[www1]}}:{{ports[https][0]}}/workers/modules/resources/export-on-load-script.js')
const importUrl =
'https://{{domains[www1]}}:{{ports[https][0]}}/workers/modules/resources/export-on-load-script.js';
if ('DedicatedWorkerGlobalScope' in self &&
self instanceof DedicatedWorkerGlobalScope) {
import(importUrl)
.then(module => postMessage(module.importedModules))
.catch(e => postMessage(['ERROR']));
} else if (
'SharedWorkerGlobalScope' in self &&
self instanceof SharedWorkerGlobalScope) {
onconnect = e => {
import(importUrl)
.then(module => e.ports[0].postMessage(module.importedModules))
.catch(error => e.ports[0].postMessage(['ERROR']));
};
}
// Import a remote origin script.
import * as module from 'https://{{domains[www1]}}:{{ports[https][0]}}/workers/modules/resources/export-on-load-script.js';
postMessage(module.importedModules);
if ('DedicatedWorkerGlobalScope' in self &&
self instanceof DedicatedWorkerGlobalScope) {
postMessage(module.importedModules);
} else if (
'SharedWorkerGlobalScope' in self &&
self instanceof SharedWorkerGlobalScope) {
onconnect = e => {
e.ports[0].postMessage(module.importedModules);
};
}
<!DOCTYPE html>
<title>SharedWorker: CSP for ES Modules</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
async function openWindow(url) {
const win = window.open(url, '_blank');
add_result_callback(() => win.close());
const msgEvent = await new Promise(resolve => window.onmessage = resolve);
assert_equals(msgEvent.data, 'LOADED');
return win;
}
function import_csp_test(
cspHeader, importType, expectedImportedModules, description) {
// Append CSP header to windowURL for static import tests since static import
// scripts should obey Window's CSP.
const windowURL = `resources/new-shared-worker-window.html` +
`${importType === 'static'
? '?pipe=header(Content-Security-Policy, ' + cspHeader + ')'
: ''}`;
// Append CSP header to scriptURL for dynamic import tests since dynamic
// import scripts should obey SharedWorker script's responce's CSP.
const scriptURL = `${importType}-import-remote-origin-script-worker.sub.js` +
`${importType === 'dynamic'
? '?pipe=header(Content-Security-Policy, ' + cspHeader + ')'
: ''}`;
promise_test(async () => {
// Open a window that has the given CSP header.
const win = await openWindow(windowURL);
// Ask the window to start a shared worker with the given CSP header.
// The shared worker doesn't inherits the window's CSP header.
// https://w3c.github.io/webappsec-csp/#initialize-global-object-csp
win.postMessage(scriptURL, '*');
const msg_event = await new Promise(resolve => window.onmessage = resolve);
assert_array_equals(msg_event.data, expectedImportedModules);
}, description);
}
// Tests for static import.
//
// Static import should obey the worker-src directive and the script-src
// directive. If the both directives are specified, the worker-src directive
// should be prioritized.
//
// "The script-src directive acts as a default fallback for all script-like
// destinations (including worker-specific destinations if worker-src is not
// present)."
// https://w3c.github.io/webappsec-csp/#directive-script-src
import_csp_test(
"worker-src 'self' 'unsafe-inline'", "static",
['ERROR'],
"worker-src 'self' directive should disallow cross origin static import.");
import_csp_test(
"worker-src * 'unsafe-inline'", "static",
["export-on-load-script.js"],
"worker-src * directive should allow cross origin static import.");
import_csp_test(
"script-src 'self' 'unsafe-inline'", "static",
['ERROR'],
"script-src 'self' directive should disallow cross origin static import.");
import_csp_test(
"script-src * 'unsafe-inline'", "static",
["export-on-load-script.js"],
"script-src * directive should allow cross origin static import.");
import_csp_test(
"worker-src *; script-src 'self' 'unsafe-inline'", "static",
["export-on-load-script.js"],
"worker-src * directive should override script-src 'self' directive and " +
"allow cross origin static import.");
import_csp_test(
"worker-src 'self'; script-src * 'unsafe-inline'", "static",
['ERROR'],
"worker-src 'self' directive should override script-src * directive and " +
"disallow cross origin static import.");
// Tests for dynamic import.
//
// Dynamic import should obey SharedWorker script's CSP instead of parent
// Window's CSP.
//
// Dynamic import should obey the script-src directive instead of the worker-src
// directive according to the specs:
//
// Dynamic import has the "script" destination.
// Step 3: "Fetch a single module script graph given url, ..., "script", ..."
// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-an-import()-module-script-graph
//
// The "script" destination should obey the script-src CSP directive.
// "The script-src directive acts as a default fallback for all script-like
// destinations (including worker-specific destinations if worker-src is not
// present)."
// https://w3c.github.io/webappsec-csp/#directive-script-src
import_csp_test(
"script-src 'self' 'unsafe-inline'", "dynamic",
['ERROR'],
"script-src 'self' directive should disallow cross origin dynamic import.");
import_csp_test(
"script-src * 'unsafe-inline'", "dynamic",
["export-on-load-script.js"],
"script-src * directive should allow cross origin dynamic import.");
import_csp_test(
"worker-src 'self' 'unsafe-inline'", "dynamic",
["export-on-load-script.js"],
"worker-src 'self' directive should not take effect on dynamic import.");
</script>
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