From d49968742cb5af8ed3e93fb1073f2a8249245e58 Mon Sep 17 00:00:00 2001 From: Hiroshige Hayashizaki Date: Fri, 9 Nov 2018 07:25:45 -0800 Subject: [PATCH] Add redirected cases to CSP/import tests in wpt/worklets Also this CL replaces some of empty-worklet-script.js usage in CSP tests with empty-worklet-script-with-cors-header.js to make sure worklets are rejected due to CSP, not CORS. Change-Id: Ie463d206254c4c6728a79dae0ad79e4f7e333b92 Reviewed-on: https://chromium-review.googlesource.com/c/1312146 Commit-Queue: Hiroshige Hayashizaki Reviewed-by: Hiroki Nakagawa Cr-Commit-Position: refs/heads/master@{#606846} --- worklets/resources/csp-tests.js | 248 +++++++++++------- ...nsecure-origin-empty-worklet-script.sub.js | 2 +- ...gin-redirected-empty-worklet-script.sub.js | 5 + ...-remote-origin-empty-worklet-script.sub.js | 2 +- ...gin-redirected-empty-worklet-script.sub.js | 1 + worklets/resources/import-tests.js | 23 ++ 6 files changed, 183 insertions(+), 98 deletions(-) create mode 100644 worklets/resources/import-insecure-origin-redirected-empty-worklet-script.sub.js create mode 100644 worklets/resources/import-remote-origin-redirected-empty-worklet-script.sub.js diff --git a/worklets/resources/csp-tests.js b/worklets/resources/csp-tests.js index 0de1daae22853f..d2ca05f3998291 100644 --- a/worklets/resources/csp-tests.js +++ b/worklets/resources/csp-tests.js @@ -22,109 +22,165 @@ function openWindowAndExpectResult(windowURL, scriptURL, type, expectation) { // Usage: // runContentSecurityPolicyTests("paint"); function runContentSecurityPolicyTests(workletType) { - promise_test(t => { - const kWindowURL = - 'resources/addmodule-window.html?pipe=header(' + - 'Content-Security-Policy, script-src \'self\' \'unsafe-inline\')'; - const kScriptURL = - get_host_info().HTTPS_REMOTE_ORIGIN + - '/worklets/resources/import-empty-worklet-script-with-cors-header.js'; - return openWindowAndExpectResult( - kWindowURL, kScriptURL, workletType, 'REJECTED'); - }, 'Importing a remote-origin worklet script should be blocked by the ' + - 'script-src \'self\' directive.'); + runSrcTests(workletType); + runMixedContentTests(workletType); + runUpgradeInsecureRequestsTests(workletType); +} - promise_test(t => { - const kWindowURL = +// script-src and worker-src tests. +function runSrcTests(workletType) { + const kWindowConfigs = [ + { + 'windowURL': 'resources/addmodule-window.html?pipe=header(' + - 'Content-Security-Policy, script-src \'self\' \'unsafe-inline\')'; - const kScriptURL = 'import-remote-origin-empty-worklet-script.sub.js'; - return openWindowAndExpectResult( - kWindowURL, kScriptURL, workletType, 'REJECTED'); - }, 'Importing a remote-origin script from a same-origin worklet script ' + - 'should be blocked by the script-src \'self\' directive.'); - - promise_test(t => { - const kWindowURL = + 'Content-Security-Policy, script-src \'self\' \'unsafe-inline\')', + 'crossOriginExpectation': 'REJECTED', + 'message': 'should be blocked by the script-src \'self\' directive.' + }, + { + 'windowURL': 'resources/addmodule-window.html?pipe=header(' + - 'Content-Security-Policy, script-src * \'unsafe-inline\')'; - const kScriptURL = - get_host_info().HTTPS_REMOTE_ORIGIN + - '/worklets/resources/empty-worklet-script-with-cors-header.js'; - return openWindowAndExpectResult( - kWindowURL, kScriptURL, workletType, 'RESOLVED'); - }, 'Importing a remote-origin worklet script should not be blocked ' + - 'because the script-src * directive allows it.'); - - promise_test(t => { - const kWindowURL = + 'Content-Security-Policy, script-src ' + location.origin + ' ' + + get_host_info().HTTPS_REMOTE_ORIGIN + ' \'unsafe-inline\')', + 'crossOriginExpectation': 'RESOLVED', + 'message': + 'should not be blocked because the script-src directive ' + + 'specifying the origin allows it.' + }, + { + 'windowURL': 'resources/addmodule-window.html?pipe=header(' + - 'Content-Security-Policy, script-src * \'unsafe-inline\')'; - // A worklet on HTTPS_REMOTE_ORIGIN will import a child script on - // HTTPS_REMOTE_ORIGIN. - const kScriptURL = - get_host_info().HTTPS_REMOTE_ORIGIN + - '/worklets/resources/import-empty-worklet-script-with-cors-header.js'; - return openWindowAndExpectResult( - kWindowURL, kScriptURL, workletType, 'RESOLVED'); - }, 'Importing a remote-origin script from a remote-origin worklet script '+ - 'should not be blocked because the script-src * directive allows it.'); - - promise_test(t => { - const kWindowURL = + 'Content-Security-Policy, script-src * \'unsafe-inline\')', + 'crossOriginExpectation': 'RESOLVED', + 'message': + 'should not be blocked because the script-src * directive allows it.' + }, + { + 'windowURL': 'resources/addmodule-window.html?pipe=header(' + - 'Content-Security-Policy, worker-src \'self\' \'unsafe-inline\')'; - const kScriptURL = - get_host_info().HTTPS_REMOTE_ORIGIN + - '/worklets/resources/empty-worklet-script-with-cors-header.js'; - return openWindowAndExpectResult( - kWindowURL, kScriptURL, workletType, 'RESOLVED'); - }, 'Importing a remote-origin worklet script should not be blocked by ' + - 'the worker-src directive because worklets obey the script-src ' + - 'directive.'); + 'Content-Security-Policy, worker-src \'self\' \'unsafe-inline\')', + 'crossOriginExpectation': 'RESOLVED', + 'message': + 'should not be blocked by the worker-src directive ' + + 'because worklets obey the script-src directive.' + } + ]; + for (const windowConfig of kWindowConfigs) { + promise_test(t => { + const kScriptURL = + get_host_info().HTTPS_REMOTE_ORIGIN + + '/worklets/resources/empty-worklet-script-with-cors-header.js'; + return openWindowAndExpectResult( + windowConfig.windowURL, kScriptURL, workletType, + windowConfig.crossOriginExpectation); + }, + 'A remote-origin worklet ' + windowConfig.message); - promise_test(t => { - const kWindowURL = 'resources/addmodule-window.html'; - const kScriptURL = - get_host_info().HTTP_ORIGIN + - '/worklets/resources/empty-worklet-script.js'; - return openWindowAndExpectResult( - kWindowURL, kScriptURL, workletType, 'REJECTED'); - }, 'Importing an insecure-origin worklet script should be blocked because ' + - 'of mixed contents.'); + promise_test(t => { + const kScriptURL = 'import-remote-origin-empty-worklet-script.sub.js'; + return openWindowAndExpectResult( + windowConfig.windowURL, kScriptURL, workletType, + windowConfig.crossOriginExpectation); + }, + 'A same-origin worklet importing a remote-origin script ' + + windowConfig.message); - promise_test(t => { - const kWindowURL = 'resources/addmodule-window.html?pipe=header(' + - 'Content-Security-Policy, upgrade-insecure-requests)'; - // This test relies on some unintuitive cleverness due to WPT's test setup: - // 'Upgrade-Insecure-Requests' does not upgrade the port number, so we use - // URLs in the form `http://[host]:[https-port]`. If the upgrade fails, the - // load will fail, as we don't serve HTTP over the secure port. - const kHost = get_host_info().ORIGINAL_HOST; - const kPort = get_host_info().HTTPS_PORT; - const kScriptURL = - `http://${kHost}:${kPort}/worklets/resources/empty-worklet-script.js`; - return openWindowAndExpectResult( - kWindowURL, kScriptURL, workletType, 'RESOLVED'); - }, 'Importing an insecure-origin worklet script should not be blocked ' + - 'because the upgrade-insecure-requests directive translates it as the ' + - 'secure origin.'); + promise_test(t => { + // A worklet on HTTPS_REMOTE_ORIGIN will import a child script on + // HTTPS_REMOTE_ORIGIN. + const kScriptURL = + get_host_info().HTTPS_REMOTE_ORIGIN + + '/worklets/resources/import-empty-worklet-script-with-cors-header.js'; + return openWindowAndExpectResult( + windowConfig.windowURL, kScriptURL, workletType, + windowConfig.crossOriginExpectation); + }, + 'A remote-origin worklet importing a remote-origin script ' + + windowConfig.message); + + promise_test(t => { + const kScriptURL = + '/common/redirect.py?location=' + encodeURIComponent( + get_host_info().HTTPS_REMOTE_ORIGIN + + '/worklets/resources/empty-worklet-script-with-cors-header.js'); + return openWindowAndExpectResult( + windowConfig.windowURL, kScriptURL, workletType, + windowConfig.crossOriginExpectation); + }, + 'A remote-origin-redirected worklet ' + windowConfig.message); + + promise_test(t => { + const kScriptURL = + 'import-remote-origin-redirected-empty-worklet-script.sub.js'; + return openWindowAndExpectResult( + windowConfig.windowURL, kScriptURL, workletType, + windowConfig.crossOriginExpectation); + }, + 'A same-origin worklet importing a remote-origin-redirected script ' + + windowConfig.message); + } +} + +// Mixed content tests. +function runMixedContentTests(workletType) { + const kInsecureURL = + get_host_info().HTTP_ORIGIN + + '/worklets/resources/empty-worklet-script-with-cors-header.js'; + const kScriptConfigs = [ + {URL: kInsecureURL, + message: 'An insecure-origin worklet'}, + {URL: '/common/redirect.py?location=' + encodeURIComponent(kInsecureURL), + message: 'An insecure-origin-redirected worklet'}, + {URL: 'import-insecure-origin-empty-worklet-script.sub.js', + message: 'A same-origin worklet importing an insecure-origin script'}, + {URL: 'import-insecure-origin-redirected-empty-worklet-script.sub.js', + message: 'A same-origin worklet ' + + 'importing an insecure-origin-redirected script'} + ]; + for (const scriptConfig of kScriptConfigs) { + promise_test(t => { + const kWindowURL = 'resources/addmodule-window.html'; + return openWindowAndExpectResult( + kWindowURL, scriptConfig.URL, workletType, 'REJECTED'); + }, + scriptConfig.message + ' should be blocked because of mixed contents.'); + } +} - promise_test(t => { - const kWindowURL = 'resources/addmodule-window.html'; - const kScriptURL = 'import-insecure-origin-empty-worklet-script.sub.js'; - return openWindowAndExpectResult( - kWindowURL, kScriptURL, workletType, 'REJECTED'); - }, 'Importing an insecure-origin script from a secure-origin worklet ' + - 'script should be blocked because of mixed contents.'); +// upgrade-insecure-requests tests. +function runUpgradeInsecureRequestsTests(workletType) { + // |kToBeUpgradedURL| is expected to upgraded/loaded successfully with + // upgrade-insecure-requests is specified. + // This relies on some unintuitive cleverness due to WPT's test setup: + // 'Upgrade-Insecure-Requests' does not upgrade the port number, so we use + // URLs in the form `http://[host]:[https-port]`. If the upgrade fails, the + // load will fail, as we don't serve HTTP over the secure port. + const kHost = get_host_info().ORIGINAL_HOST; + const kPort = get_host_info().HTTPS_PORT; + const kToBeUpgradedURL = + `http://${kHost}:${kPort}/worklets/resources/empty-worklet-script-with-cors-header.js`; - promise_test(t => { - const kWindowURL = 'resources/addmodule-window.html?pipe=header(' + - 'Content-Security-Policy, upgrade-insecure-requests)'; - const kScriptURL = 'import-insecure-origin-empty-worklet-script.sub.js'; - return openWindowAndExpectResult( - kWindowURL, kScriptURL, workletType, 'RESOLVED'); - }, 'Importing an insecure-origin script from a secure-origin worklet ' + - 'script should not be blocked because the upgrade-insecure-requests ' + - 'directive translates it as the secure origin.'); + const kScriptConfigs = [ + {URL: kToBeUpgradedURL, + message: 'An insecure-origin worklet'}, + {URL: '/common/redirect.py?location=' + + encodeURIComponent(kToBeUpgradedURL), + message: 'An insecure-origin-redirected worklet'}, + {URL: 'import-insecure-origin-empty-worklet-script.sub.js', + message: 'A same-origin worklet importing an insecure-origin script'}, + {URL: 'import-insecure-origin-redirected-empty-worklet-script.sub.js', + message: 'A same-origin worklet ' + + 'importing an insecure-origin-redirected script'} + ]; + for (const scriptConfig of kScriptConfigs) { + promise_test(t => { + const kWindowURL = + 'resources/addmodule-window.html?pipe=header(' + + 'Content-Security-Policy, upgrade-insecure-requests)'; + return openWindowAndExpectResult( + kWindowURL, scriptConfig.URL, workletType, 'RESOLVED'); + }, + scriptConfig.message + + ' should not be blocked because of upgrade-insecure-requests.'); + } } diff --git a/worklets/resources/import-insecure-origin-empty-worklet-script.sub.js b/worklets/resources/import-insecure-origin-empty-worklet-script.sub.js index cc7f5f348a116a..a04a2edf812122 100644 --- a/worklets/resources/import-insecure-origin-empty-worklet-script.sub.js +++ b/worklets/resources/import-insecure-origin-empty-worklet-script.sub.js @@ -2,4 +2,4 @@ // 'Upgrade-Insecure-Requests' does not upgrade the port number, so we use URLs // in the form `http://[host]:[https-port]`. If the upgrade fails, the load will // fail, as we don't serve HTTP over the secure port. -import 'http://{{host}}:{{ports[https][0]}}/worklets/resources/empty-worklet-script.js'; +import 'http://{{host}}:{{ports[https][0]}}/worklets/resources/empty-worklet-script-with-cors-header.js'; diff --git a/worklets/resources/import-insecure-origin-redirected-empty-worklet-script.sub.js b/worklets/resources/import-insecure-origin-redirected-empty-worklet-script.sub.js new file mode 100644 index 00000000000000..888d876bff9fa6 --- /dev/null +++ b/worklets/resources/import-insecure-origin-redirected-empty-worklet-script.sub.js @@ -0,0 +1,5 @@ +// Some tests rely on some unintuitive cleverness due to WPT's test setup: +// 'Upgrade-Insecure-Requests' does not upgrade the port number, so we use URLs +// in the form `http://[host]:[https-port]`. If the upgrade fails, the load will +// fail, as we don't serve HTTP over the secure port. +import '/common/redirect.py?location=http://{{host}}:{{ports[https][0]}}/worklets/resources/empty-worklet-script-with-cors-header.js'; diff --git a/worklets/resources/import-remote-origin-empty-worklet-script.sub.js b/worklets/resources/import-remote-origin-empty-worklet-script.sub.js index c30889873393c3..06c1f87618cf07 100644 --- a/worklets/resources/import-remote-origin-empty-worklet-script.sub.js +++ b/worklets/resources/import-remote-origin-empty-worklet-script.sub.js @@ -1 +1 @@ -import 'https://{{domains[www1]}}:{{ports[https][0]}}/worklets/resources/empty-worklet-script.js'; +import 'https://{{domains[www1]}}:{{ports[https][0]}}/worklets/resources/empty-worklet-script-with-cors-header.js'; diff --git a/worklets/resources/import-remote-origin-redirected-empty-worklet-script.sub.js b/worklets/resources/import-remote-origin-redirected-empty-worklet-script.sub.js new file mode 100644 index 00000000000000..7afa3523b9f30d --- /dev/null +++ b/worklets/resources/import-remote-origin-redirected-empty-worklet-script.sub.js @@ -0,0 +1 @@ +import '/common/redirect.py?location=https://{{domains[www1]}}:{{ports[https][0]}}/worklets/resources/empty-worklet-script-with-cors-header.js'; diff --git a/worklets/resources/import-tests.js b/worklets/resources/import-tests.js index 5ab841cd4a6c3f..f504588cdb065c 100644 --- a/worklets/resources/import-tests.js +++ b/worklets/resources/import-tests.js @@ -114,6 +114,29 @@ function runImportTests(worklet_type) { }, 'Importing a cross origin resource without the ' + 'Access-Control-Allow-Origin header should reject the given promise'); + promise_test(() => { + const kScriptURL = get_host_info().HTTPS_REMOTE_ORIGIN + + '/worklets/resources/empty-worklet-script.js' + + '?pipe=header(Access-Control-Allow-Origin, ' + + location.origin + ')'; + return worklet.addModule('/common/redirect.py?location=' + + encodeURIComponent(kScriptURL)) + .then(undefined_arg => { + assert_equals(undefined_arg, undefined); + }); + }, 'Importing a cross-origin-redirected resource with the ' + + 'Access-Control-Allow-Origin header should resolve the given promise'); + + promise_test(t => { + const kScriptURL = get_host_info().HTTPS_REMOTE_ORIGIN + + '/worklets/resources/empty-worklet-script.js'; + return promise_rejects(t, new DOMException('', 'AbortError'), + worklet.addModule( + '/common/redirect.py?location=' + + encodeURIComponent(kScriptURL))); + }, 'Importing a cross-origin-redirected resource without the ' + + 'Access-Control-Allow-Origin header should reject the given promise'); + promise_test(t => { const kScriptURL = 'resources/syntax-error-worklet-script.js'; return promise_rejects(t, new DOMException('', 'AbortError'),