diff options
Diffstat (limited to '')
45 files changed, 1041 insertions, 0 deletions
diff --git a/testing/web-platform/tests/content-security-policy/generic/304-response-should-update-csp.sub.html b/testing/web-platform/tests/content-security-policy/generic/304-response-should-update-csp.sub.html new file mode 100644 index 0000000000..b16eadaedc --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/304-response-should-update-csp.sub.html @@ -0,0 +1,52 @@ +<!DOCTYPE HTML> +<html> +<head> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> + <title>Test that a 304 response will update the CSP header</title> +</head> +<body> + <script> + var t1 = async_test("Test that the first frame uses nonce abc"); + var t2 = async_test("Test that the first frame does not use nonce def"); + + var t3 = async_test("Test that the second frame uses nonce def"); + var t4 = async_test("Test that the second frame does not use nonce abc"); + + var i1 = document.createElement('iframe'); + // We add a random parameter to avoid previous tests cached requests. + // We want to make sure i1 gets a 200 code and i2 gets a 304 code. + i1.src = "support/304-response.py?{{$id:uuid()}}"; + + var i2 = document.createElement('iframe'); + i2.src = "support/304-response.py?{{$id}}"; + + var load_second_frame = function() { + document.body.appendChild(i2); + } + + window.onmessage = function(e) { + if (e.source == i1.contentWindow) { + if (e.data == "abc_executed") { t1.done(); return; } + if (e.data == "script-src 'nonce-abc' 'sha256-IIB78ZS1RMMrAWpsLg/RrDbVPhI14rKm3sFOeKPYulw=';") { t2.done(); return; } + + t1.step(function() { assert_unreached("Unexpected message received"); }); + t2.step(function() { assert_unreached("Unexpected message received"); }); + } + + if (e.source == i2.contentWindow) { + if (e.data == "def_executed") { t3.done(); return; } + if (e.data == "script-src 'nonce-def' 'sha256-IIB78ZS1RMMrAWpsLg/RrDbVPhI14rKm3sFOeKPYulw=';") { t4.done(); return; } + + t3.step(function() { assert_unreached("Unexpected message received"); }); + t4.step(function() { assert_unreached("Unexpected message received"); }); + } + + }; + + i1.onload = load_second_frame; + document.body.appendChild(i1); + </script> +</body> + +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/cspro-not-enforced-in-worker.html b/testing/web-platform/tests/content-security-policy/generic/cspro-not-enforced-in-worker.html new file mode 100644 index 0000000000..784cdc8875 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/cspro-not-enforced-in-worker.html @@ -0,0 +1,22 @@ +<!DOCTYPE HTML> +<html> +<head> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> +</head> +<body> + <!-- This tests that a report only policy is not treated as enforcing when + inherited by a worker. This manifests in particular for `unsafe-eval` + in this bug crbug.com/777076 --> + <script nonce="abc"> + var t1 = async_test("Check that inline is allowed since the inherited policy is report only"); + var t2 = async_test("Check that eval is allowed since the inherited policy is report only"); + + var w = new Worker("support/eval.js"); + w.onmessage = function(e) { + if (e.data == "unsafe-inline allowed") t1.done(); + else if (e.data == "unsafe-eval allowed") t2.done(); + } + </script> +</body> +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/cspro-not-enforced-in-worker.html.sub.headers b/testing/web-platform/tests/content-security-policy/generic/cspro-not-enforced-in-worker.html.sub.headers new file mode 100644 index 0000000000..877e192bbf --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/cspro-not-enforced-in-worker.html.sub.headers @@ -0,0 +1 @@ +Content-Security-Policy-Report-Only: script-src 'self' 'nonce-abc'; diff --git a/testing/web-platform/tests/content-security-policy/generic/directive-name-case-insensitive.sub.html b/testing/web-platform/tests/content-security-policy/generic/directive-name-case-insensitive.sub.html new file mode 100644 index 0000000000..c65c59fb23 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/directive-name-case-insensitive.sub.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html> + +<head> + <meta http-equiv="Content-Security-Policy" content=" + IMg-sRC 'self' 'unsafe-inline' http://{{domains[www1]}}:{{ports[http][0]}}; + img-src 'self' 'unsafe-inline' http://{{domains[www2]}}:{{ports[http][0]}};"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> + +<body> + <script> + var t1 = async_test("Test that the www1 image is allowed to load"); + var t2 = async_test("Test that the www2 image is not allowed to load"); + var t_spv = async_test("Test that the www2 image throws a violation event"); + window.addEventListener("securitypolicyviolation", t_spv.step_func_done(function(e) { + assert_equals(e.violatedDirective, "img-src"); + assert_equals(e.blockedURI, "http://{{domains[www2]}}:{{ports[http][0]}}/content-security-policy/support/fail.png"); + })); + </script> + + <img src="http://{{domains[www1]}}:{{ports[http][0]}}/content-security-policy/support/pass.png" + onload="t1.done();" + onerror="t1.step(function() { assert_unreached('www1 image should have loaded'); t1.done(); });"> + + <img src="http://{{domains[www2]}}:{{ports[http][0]}}/content-security-policy/support/fail.png" + onerror="t2.done();" + onload="t2.step(function() { assert_unreached('www2 image should not have loaded'); t2.done(); });"> +</body> + +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/duplicate-directive.sub.html b/testing/web-platform/tests/content-security-policy/generic/duplicate-directive.sub.html new file mode 100644 index 0000000000..0ab708356c --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/duplicate-directive.sub.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html> + +<head> + <!-- Programmatically converted from a WebKit Reftest, please forgive resulting idiosyncracies.--> + <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-inline'; script-src 'none'; connect-src 'self';"> + <title>duplicate-directive</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="../support/logTest.sub.js?logs=[]"></script> + <script src='../support/alertAssert.sub.js?alerts=["PASS (1/1)"]'></script> + <script> + window.addEventListener('securitypolicyviolation', function(e) { + alert_assert("FAIL"); + }); + alert_assert('PASS (1/1)'); + </script> +</head> + +<body> + <p> + This tests the effect of duplicated directives. It passes if the alert_assert() is executed. + </p> + <div id="log"></div> +</body> + +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/eval-typecheck-callout-order.tentative.html b/testing/web-platform/tests/content-security-policy/generic/eval-typecheck-callout-order.tentative.html new file mode 100644 index 0000000000..0be7cf29a2 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/eval-typecheck-callout-order.tentative.html @@ -0,0 +1,28 @@ +<!DOCTYPE HTML> +<html> +<head> + <script src='/resources/testharness.js' nonce='abc'></script> + <script src='/resources/testharnessreport.js' nonce='abc'></script> + <title>Test for order of Type(evalInput) and host callout</title> +</head> +<body> + <div id='log'></div> + + <script nonce='abc'> + test(function() { + assert_throws_js(EvalError, function() { + eval("0"); + }, "eval of a string should reach host callout"); + }, "eval of a string should be checked by CSP"); + + test(function() { + let array = ["0"]; + assert_equals( + eval(array), + array, + "eval is identity when applied to non-strings"); + }, "eval of a non-string should not be checked by CSP"); + </script> + +</body> +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/eval-typecheck-callout-order.tentative.html.headers b/testing/web-platform/tests/content-security-policy/generic/eval-typecheck-callout-order.tentative.html.headers new file mode 100644 index 0000000000..85de8bd415 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/eval-typecheck-callout-order.tentative.html.headers @@ -0,0 +1 @@ +Content-Security-Policy: script-src 'nonce-abc' diff --git a/testing/web-platform/tests/content-security-policy/generic/fail-0_1.js b/testing/web-platform/tests/content-security-policy/generic/fail-0_1.js new file mode 100644 index 0000000000..5c580273dc --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/fail-0_1.js @@ -0,0 +1,3 @@ +(function () { + scriptsrc1.step(function() { assert_unreached('Unsafe inline script ran.') }); +})(); diff --git a/testing/web-platform/tests/content-security-policy/generic/filesystem-urls-do-not-match-self.sub.html b/testing/web-platform/tests/content-security-policy/generic/filesystem-urls-do-not-match-self.sub.html new file mode 100644 index 0000000000..afb272cf36 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/filesystem-urls-do-not-match-self.sub.html @@ -0,0 +1,60 @@ +<!DOCTYPE html> +<html> + +<head> + <!-- Programmatically converted from a WebKit Reftest, please forgive resulting idiosyncracies.--> + <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline'; connect-src 'self';"> + <title>filesystem-urls-do-not-match-self</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src='../support/logTest.sub.js?logs=["violated-directive=script-src-elem"]'></script> + <script src="../support/alertAssert.sub.js?alerts=[]"></script> +</head> + +<body> + <p> + filesystem: URLs are same-origin with the page in which they were created, but explicitly do not match the 'self' or '*' source in CSP directives because they are more akin to 'unsafe-inline' content.. + </p> + <script> + window.addEventListener('securitypolicyviolation', function(e) { + log("violated-directive=" + e.violatedDirective); + }); + + if(!window.webkitRequestFileSystem) { + t_log = async_test(); + t_log.set_status(t_log.NOTRUN, "No filesystem:// support, cannot run test."); + t_log.phase = t_log.phases.HAS_RESULT; + t_log.done(); + log("violated-directive=script-src"); // simulate needed logs to pass test + } else { + function fail() { + alert_assert("FAIL!"); + } + window.webkitRequestFileSystem( + TEMPORARY, 1024 * 1024 /*1MB*/ , function(fs) { + fs.root.getFile('fail.js', { + create: true + }, function(fileEntry) { + fileEntry.createWriter(function(fileWriter) { + fileWriter.onwriteend = function(e) { + var script = document.createElement('script'); + script.src = fileEntry.toURL('application/javascript'); + document.body.appendChild(script); + }; + // Create a new Blob and write it to pass.js. + var b = new Blob(['fail();'], { + type: 'application/javascript' + }); + fileWriter.write(b); + }); + }); + }); + } + + + </script> + <div id="log"></div> + +</body> + +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/filesystem-urls-match-filesystem.sub.html b/testing/web-platform/tests/content-security-policy/generic/filesystem-urls-match-filesystem.sub.html new file mode 100644 index 0000000000..f629228f9f --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/filesystem-urls-match-filesystem.sub.html @@ -0,0 +1,57 @@ +<!DOCTYPE html> +<html> + +<head> + <!-- Programmatically converted from a WebKit Reftest, please forgive resulting idiosyncracies.--> + <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' filesystem:; connect-src 'self';"> + <title>filesystem-urls-match-filesystem</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src='../support/logTest.sub.js?logs=["PASS (1/1)"]'></script> + <script src="../support/alertAssert.sub.js?alerts=[]"></script> +</head> + +<body> + <p> + filesystem: URLs are same-origin with the page in which they were created, but explicitly do not match the 'self' or '*' source in CSP directives because they are more akin to 'unsafe-inline' content, but should match filesystem: source. + </p> + <script> + window.addEventListener('securitypolicyviolation', function(e) { + log("Fail"); + }); + + if(!window.webkitRequestFileSystem) { + t_log.set_status(t_log.NOTRUN, "No filesystem:// support, cannot run test."); + t_log.phase = t_log.phases.HAS_RESULT; + t_log.done(); + log("PASS (1/1)"); // simulate needed logs to pass test + } else { + function pass() { + log("PASS (1/1)"); + } + window.webkitRequestFileSystem( + TEMPORARY, 1024 * 1024 /*1MB*/ , function(fs) { + fs.root.getFile('pass.js', { + create: true + }, function(fileEntry) { + fileEntry.createWriter(function(fileWriter) { + fileWriter.onwriteend = function(e) { + var script = document.createElement('script'); + script.src = fileEntry.toURL('application/javascript'); + document.body.appendChild(script); + }; + // Create a new Blob and write it to pass.js. + var b = new Blob(['pass();'], { + type: 'application/javascript' + }); + fileWriter.write(b); + }); + }); + }); + } + + </script> + <div id="log"></div> +</body> + +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/generic-0_1-img-src.html b/testing/web-platform/tests/content-security-policy/generic/generic-0_1-img-src.html new file mode 100644 index 0000000000..71ff3219b6 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/generic-0_1-img-src.html @@ -0,0 +1,38 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>default-src should cascade to img-src directive</title> + <meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-inline';"> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> + <script src='../support/siblingPath.js'></script> +</head> +<body> + <h1>default-src should cascade to img-src directive</h1> + <div id='log'></div> + + <script> + var imgsrc = async_test("Verify cascading of default-src to img-src policy"); + var onerrorFired = false; + var t_spv = async_test("Should fire violation events for every failed violation"); + + window.addEventListener("securitypolicyviolation", t_spv.step_func_done(function(e) { + assert_equals(e.violatedDirective, "img-src"); + })); + </script> + + <img id='imgfail' src='' + onload='imgsrc.step(function() { assert_unreached("Image load was not blocked."); });' + onerror='onerrorFired = true;'> + <img src='../support/pass.png' + onload='imgsrc.step(function() { assert_true(true, "Image load was blocked."); });'> + + <script> + document.getElementById('imgfail').src = buildSiblingPath('www1', '../support/fail.png'); + onload = function() { + imgsrc.step(function() { assert_true(onerrorFired, "onerror handler for blocked img didn't fire");}); + imgsrc.done(); + } + </script> +</body> +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/generic-0_1-script-src.html b/testing/web-platform/tests/content-security-policy/generic/generic-0_1-script-src.html new file mode 100644 index 0000000000..b374b8b88e --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/generic-0_1-script-src.html @@ -0,0 +1,38 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>default-src should cascade to script-src directive</title> + <meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-inline';"> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> + <script src='../support/siblingPath.js'></script> +</head> +<body> + <h1>default-src should cascade to script-src directive</h1> + <div id='log'></div> + + <script> + var scriptsrc1 = async_test("Verify cascading of default-src to script-src policy: block"); + var scriptsrc2 = async_test("Verify cascading of default-src to script-src policy: allow"); + var allowedScriptRan = false; + var t_spv = async_test("Should fire violation events for every failed violation"); + + window.addEventListener("securitypolicyviolation", t_spv.step_func_done(function(e) { + assert_equals(e.violatedDirective, "script-src-elem"); + })); + </script> + + <script src='pass-0_1.js'></script> + + <script> + var inlineScript = document.createElement('script'); + inlineScript.src = buildSiblingPath('www1', 'fail-0_1.js'); + document.getElementById('log').appendChild(inlineScript); + onload = function() { + scriptsrc1.done(); + scriptsrc2.step( function() { assert_true(allowedScriptRan, "allowed script didn't run") }); + scriptsrc2.done(); + } + </script> +</body> +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/generic-0_10.sub.html b/testing/web-platform/tests/content-security-policy/generic/generic-0_10.sub.html new file mode 100644 index 0000000000..62b69fb8fd --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/generic-0_10.sub.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>test implicit port number matching (requires port 80)</title> + <meta http-equiv="Content-Security-Policy content="script-src 'self' {{domains[www]}} 'unsafe-inline';"> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> + <script> + var t = async_test("Test that script does not fire violation event"); + window.addEventListener("securitypolicyviolation", t.unreached_func("Should not have fired a violation event")); + + var head = document.getElementsByTagName('head')[0]; + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = "http://{{domains[www]}}/content-security-policy/generic/positiveTest.js"; + head.appendChild(script); + </script> + + <script> + t.done(); + </script> +</head> +<body> + <h1>test implicit port number matching (requires port 80)</h1> + <div id='log'></div> +</body> +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/generic-0_10_1.sub.html b/testing/web-platform/tests/content-security-policy/generic/generic-0_10_1.sub.html new file mode 100644 index 0000000000..f48c1e3c56 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/generic-0_10_1.sub.html @@ -0,0 +1,26 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>implicit port number matching fails with a different port</title> + <meta http-equiv="Content-Security-Policy" content="script-src 'self' www.{{host}} 'unsafe-inline';"> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> + <script src='negativeTests.js'></script> + <script> + var t_spv = async_test("Should fire violation events for every failed violation"); + window.addEventListener("securitypolicyviolation", t_spv.step_func_done(function(e) { + assert_equals(e.violatedDirective, "script-src-elem"); + })); + + var head = document.getElementsByTagName('head')[0]; + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = "http://www." + location.hostname + ":{{ports[http][1]}}/content-security-policy/generic/unreached.js"; + head.appendChild(script); + </script> +</head> +<body> + <h1>implicit port number matching fails with a different port</h1> + <div id='log'></div> +</body> +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/generic-0_2.html b/testing/web-platform/tests/content-security-policy/generic/generic-0_2.html new file mode 100644 index 0000000000..4f295441cd --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/generic-0_2.html @@ -0,0 +1,28 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>'self' keyword positive test</title> + <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'nonce-abc';"> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> + <script nonce='abc'> + var t_spv = async_test("Should fire violation events for every failed violation"); + window.addEventListener( + "securitypolicyviolation", t_spv.unreached_func("securitypolicyviolation should not be emitted")); + + window.addEventListener("load", function() { + t_spv.done(); + }); + </script> + <script src='positiveTest.js'></script> + <script nonce='abc'> + test(function() { + assert_true(window.cspPositiveTest); + }, "Allows scripts from the same host."); + </script> +</head> +<body> + <h1>'self' keyword positive test</h1> + <div id='log'></div> +</body> +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/generic-0_2_2.sub.html b/testing/web-platform/tests/content-security-policy/generic/generic-0_2_2.sub.html new file mode 100644 index 0000000000..6cb75e31ae --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/generic-0_2_2.sub.html @@ -0,0 +1,26 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>'self' fails with a different port</title> + <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';"> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> + <script src='negativeTests.js'></script> + <script> + var t_spv = async_test("Should fire violation events for every failed violation"); + window.addEventListener("securitypolicyviolation", t_spv.step_func_done(function(e) { + assert_equals(e.violatedDirective, "script-src-elem"); + })); + + var head = document.getElementsByTagName('head')[0]; + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = "http://" + location.hostname + ":{{ports[http][1]}}/content-security-policy/generic/unreached.js"; + head.appendChild(script); + </script> +</head> +<body> + <h1>'self' fails with a different port</h1> + <div id='log'></div> +</body> +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/generic-0_2_3.html b/testing/web-platform/tests/content-security-policy/generic/generic-0_2_3.html new file mode 100644 index 0000000000..d9c230d2a5 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/generic-0_2_3.html @@ -0,0 +1,26 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>'self' fails with a different host (including sub-host e.g. foo.com as self with content from bar.foo.com)</title> + <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';"> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> + <script src='negativeTests.js'></script> + <script> + var t_spv = async_test("Should fire violation events for every failed violation"); + window.addEventListener("securitypolicyviolation", t_spv.step_func_done(function(e) { + assert_equals(e.violatedDirective, "script-src-elem"); + })); + + var head = document.getElementsByTagName('head')[0]; + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = "http://www." + location.hostname + ":" + location.port + "/content-security-policy/generic/unreached.js"; + head.appendChild(script); + </script> +</head> +<body> + <h1>'self' fails with a different host (including sub-host e.g. foo.com as self with content from bar.foo.com)</h1> + <div id='log'></div> +</body> +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/generic-0_8.sub.html b/testing/web-platform/tests/content-security-policy/generic/generic-0_8.sub.html new file mode 100644 index 0000000000..a9a76c825e --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/generic-0_8.sub.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>test wildcard host name matching (asterisk as a subdomain of the current domain)</title> + <meta http-equiv="Content-Security-Policy" content="script-src 'self' *.{{host}}:{{ports[http][0]}} 'unsafe-inline';"> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> + <script src='wildcardHostTest.js'></script> + <script> + var t = async_test("Test that script does not fire violation event"); + window.addEventListener("securitypolicyviolation", t.unreached_func("Should not have fired a violation event")); + window.addEventListener("load", t.step_func(function() { + assert_true(window.wildcardHostTestRan); + t.done(); + })); + var head = document.getElementsByTagName('head')[0]; + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = "http://www." + location.hostname + ":" + location.port + "/content-security-policy/generic/wildcardHostTestSuceeds.js"; + head.appendChild(script); + </script> +</head> +<body> + <h1>test wildcard host name matching (asterisk as a subdomain of the current domain)</h1> + <div id='log'></div> +</body> +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/generic-0_8_1.sub.html b/testing/web-platform/tests/content-security-policy/generic/generic-0_8_1.sub.html new file mode 100644 index 0000000000..c326af0e54 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/generic-0_8_1.sub.html @@ -0,0 +1,31 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>test wildcard host name matching (asterisk as part of a subdomain is not accepted)</title> + <script> + var t_spv = async_test("Should fire violation events for every failed violation"); + var spvEvent; + window.addEventListener("securitypolicyviolation", t_spv.step_func(function(e) { + spvEvent = e; + })); + addEventListener("load", t_spv.step_func_done(function() { + assert_true(!!spvEvent); + assert_equals(spvEvent.violatedDirective, "script-src-elem"); + })); + + var head = document.getElementsByTagName('head')[0]; + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = "http://www." + location.hostname + ":" + location.port + "/content-security-policy/generic/wildcardHostTestSuceeds.js"; + head.appendChild(script); + </script> + <meta http-equiv="Content-Security-Policy" content="script-src 'self' *w.{{host}}:{{ports[http][0]}} w*.{{host}}:{{ports[http][0]}} 'unsafe-inline';"> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> + <script src='wildcardHostTestFailure.js'></script> +</head> +<body> + <h1>test wildcard host name matching (asterisk as part of a subdomain is not accepted)</h1> + <div id='log'></div> +</body> +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/generic-0_9.sub.html b/testing/web-platform/tests/content-security-policy/generic/generic-0_9.sub.html new file mode 100644 index 0000000000..564927bd7e --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/generic-0_9.sub.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>test wildcard port number matching</title> + <meta http-equiv="Content-Security-Policy" content="script-src 'self' {{host}}:* 'unsafe-inline';"> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> + <script src='wildcardPortTest.js'></script> + <script> + var t = async_test("Test that script does not fire violation event"); + window.addEventListener("securitypolicyviolation", t.unreached_func("Should not have fired a violation event")); + window.addEventListener("load", function() { + t.done(); + }); + + var head = document.getElementsByTagName('head')[0]; + var script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = "http://" + location.hostname + ":{{ports[http][1]}}/content-security-policy/generic/wildcardPortTestSuceeds.js"; + head.appendChild(script); + </script> +</head> +<body> + <h1>test wildcard port number matching</h1> + <div id='log'></div> +</body> +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/invalid-characters-in-policy.html b/testing/web-platform/tests/content-security-policy/generic/invalid-characters-in-policy.html new file mode 100644 index 0000000000..e46449117f --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/invalid-characters-in-policy.html @@ -0,0 +1,75 @@ +<!DOCTYPE HTML> +<html> +<head> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> +</head> +<body> + <script> + var tests = [ + // Make sure that csp works properly in normal situations + { + "csp": "", + "expected": true, + "name": "Should load image without any CSP", + }, + { + "csp": "img-src 'none';", + "expected": false, + "name": "Should not load image with 'none' CSP", + }, + + // Now test with non-ASCII characters. + { + "csp": "img-src 'none' \u00A1invalid-source; style-src 'none'", + "expected": true, + "name": "Non-ASCII character in directive value should drop the whole directive.", + }, + { + "csp": "img-src ‘none’;", + "expected": true, + "name": "Non-ASCII quote character in directive value should drop the whole directive.", + }, + { + "csp": "img-src 'none'; style-src \u00A1invalid-source 'none'", + "expected": false, + "name": "Non-ASCII character in directive value should not affect other directives.", + }, + { + "csp": "img-src 'none'; style\u00A1-src 'none'", + "expected": false, + "name": "Non-ASCII character in directive name should not affect other directives.", + }, + ]; + + tests.forEach(test => { + async_test(t => { + var url = "support/load_img_and_post_result_meta.sub.html?csp=" + + encodeURIComponent(test.csp); + test_image_loads_as_expected(test, t, url); + }, test.name + " - meta tag"); + + async_test(t => { + var url = "support/load_img_and_post_result_header.html?csp=" + + encodeURIComponent(test.csp); + test_image_loads_as_expected(test, t, url); + }, test.name + " - HTTP header"); + }); + + function test_image_loads_as_expected(test, t, url) { + var i = document.createElement('iframe'); + i.src = url; + window.addEventListener('message', t.step_func(function(e) { + if (e.source != i.contentWindow) return; + if (test.expected) { + assert_equals(e.data, "img loaded"); + } else { + assert_equals(e.data, "img not loaded"); + } + t.done(); + })); + document.body.appendChild(i); + } + </script> +</body> +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/negativeTests.js b/testing/web-platform/tests/content-security-policy/generic/negativeTests.js new file mode 100644 index 0000000000..44b4d7f683 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/negativeTests.js @@ -0,0 +1,3 @@ +var t1 = async_test("Prevents access to external scripts."); + +onload = function() {t1.done();} diff --git a/testing/web-platform/tests/content-security-policy/generic/no-default-src.sub.html b/testing/web-platform/tests/content-security-policy/generic/no-default-src.sub.html new file mode 100644 index 0000000000..9a89ec05ad --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/no-default-src.sub.html @@ -0,0 +1,41 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>no default src doesn't behave exactly like *</title> + <meta name="timeout" content="long"> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> + <script src="../support/alertAssert.sub.js?alerts=[]"> </script> + <script src='positiveTest.js'></script> + <!-- enforcing policy: foobar; report-uri ... + --> +</head> +<body> + <h1>no default src doesn't behave exactly like *</h1> + This page has a CSP header but an unknown directive. + This should have no impact on an img loaded from a data: + uri, or an inline script, although that would be blocked by a default-src policy of *. + <br> + <img src='data:image/png;base64,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'> + <script> + setup({ explicit_done: true }); + + test(function() { + assert_true(window.cspPositiveTest); + }, "Allows scripts from the same host."); + </script> + + <div id='log'></div> + + <script> + var script = document.createElement('script'); + script.src = '../support/checkReport.sub.js?reportExists=false'; + script.async = true; + script.defer = true; + script.addEventListener('load', function() { + done(); + }); + document.body.appendChild(script); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/no-default-src.sub.html.sub.headers b/testing/web-platform/tests/content-security-policy/generic/no-default-src.sub.html.sub.headers new file mode 100644 index 0000000000..b40d6ffbab --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/no-default-src.sub.html.sub.headers @@ -0,0 +1,6 @@ +Expires: Mon, 26 Jul 1997 05:00:00 GMT +Cache-Control: no-store, no-cache, must-revalidate +Cache-Control: post-check=0, pre-check=0, false +Pragma: no-cache +Set-Cookie: no-default-src={{$id:uuid()}}; Path=/content-security-policy/generic/ +Content-Security-Policy: foobar; report-uri /reporting/resources/report.py?op=put&reportID={{$id}} diff --git a/testing/web-platform/tests/content-security-policy/generic/only-valid-whitespaces-are-allowed.html b/testing/web-platform/tests/content-security-policy/generic/only-valid-whitespaces-are-allowed.html new file mode 100644 index 0000000000..9b3636c9fe --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/only-valid-whitespaces-are-allowed.html @@ -0,0 +1,67 @@ +<!DOCTYPE HTML> +<html> +<head> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> +</head> +<body> + <script> + var tests = [ + // Make sure that csp works properly in normal situations + { "csp": "", "expected": true, "name": "Should load image without any CSP" }, + { "csp": "img-src 'none';", "expected": false, "name": "Should not load image with 'none' CSP" }, + // Ensure ASCII whitespaces are properly parsed + // ASCII whitespace is U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, or U+0020 SPACE. + + // between directive name and value + { "csp": "img-src\u0009'none';", "expected": false, "name": "U+0009 TAB should be properly parsed between directive name and value" }, + { "csp": "img-src\u000C'none';", "expected": false, "name": "U+000C FF should be properly parsed between directive name and value" }, + { "csp": "img-src\u000A'none';", "expected": false, "name": "U+000A LF should be properly parsed between directive name and value" }, + { "csp": "img-src\u000D'none';", "expected": false, "name": "U+000D CR should be properly parsed between directive name and value" }, + { "csp": "img-src\u0020'none';", "expected": false, "name": "U+0020 SPACE should be properly parsed between directive name and value" }, + + // inside directive value + { "csp": "img-src http://example.com\u0009http://example2.com;", "expected": false, "name": "U+0009 TAB should be properly parsed inside directive value" }, + { "csp": "img-src http://example.com\u000Chttp://example2.com;", "expected": false, "name": "U+000C FF should be properly parsed inside directive value" }, + { "csp": "img-src http://example.com\u000Ahttp://example2.com;", "expected": false, "name": "U+000A LF should be properly parsed inside directive value" }, + { "csp": "img-src http://example.com\u000Dhttp://example2.com;", "expected": false, "name": "U+000D CR should be properly parsed inside directive value" }, + { "csp": "img-src http://example.com\u0020http://example2.com;", "expected": false, "name": "U+0020 SPACE should be properly parsed inside directive value" }, + + // Ensure nbsp (U+00A0) is not considered a valid whitespace + // https://github.com/webcompat/web-bugs/issues/18902 has more details about why this particularly relevant + { "csp": "img-src\u00A0'none';", "expected": true, "name": "U+00A0 NBSP should not be parsed between directive name and value" }, + { "csp": "img-src http://example.com\u00A0http://example2.com;", "expected": true, "name": "U+00A0 NBSP should not be parsed inside directive value" }, + ]; + + tests.forEach(test => { + async_test(t => { + var url = "support/load_img_and_post_result_meta.sub.html?csp=" + encodeURIComponent(test.csp); + test_image_loads_as_expected(test, t, url); + }, test.name + " - meta tag"); + + // We can't test csp delivered in an HTTP header if we're testing CR/LF characters + if (test.csp.indexOf("\u000A") == -1 && test.csp.indexOf("\u000D") == -1) { + async_test(t => { + var url = "support/load_img_and_post_result_header.html?csp=" + encodeURIComponent(test.csp); + test_image_loads_as_expected(test, t, url); + }, test.name + " - HTTP header"); + } + }); + + function test_image_loads_as_expected(test, t, url) { + var i = document.createElement('iframe'); + i.src = url; + window.addEventListener('message', t.step_func(function(e) { + if (e.source != i.contentWindow) return; + if (test.expected) { + assert_equals(e.data, "img loaded"); + } else { + assert_equals(e.data, "img not loaded"); + } + t.done(); + })); + document.body.appendChild(i); + } + </script> +</body> +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/pass-0_1.js b/testing/web-platform/tests/content-security-policy/generic/pass-0_1.js new file mode 100644 index 0000000000..3a08dd5621 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/pass-0_1.js @@ -0,0 +1,3 @@ +(function () { + allowedScriptRan = true; +})(); diff --git a/testing/web-platform/tests/content-security-policy/generic/policy-does-not-affect-child.sub.html b/testing/web-platform/tests/content-security-policy/generic/policy-does-not-affect-child.sub.html new file mode 100644 index 0000000000..e36ca477b5 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/policy-does-not-affect-child.sub.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html> + +<head> + <!-- Programmatically converted from a WebKit Reftest, please forgive resulting idiosyncracies.--> + <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'nonce-abc';"> + <title>object-src-url-blocked</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src='../support/logTest.sub.js?logs=["PASS"]'></script> + <script src="../support/alertAssert.sub.js?alerts=[]"></script> +</head> + +<body> + <script nonce='abc'> + window.onmessage = function(e) { + log(e.data); + } + </script> + <iframe src="support/log-pass.html"></iframe> + <div id="log"></div> +</body> + +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html b/testing/web-platform/tests/content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html new file mode 100644 index 0000000000..e21bede418 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html @@ -0,0 +1,43 @@ +<!DOCTYPE HTML> +<html> +<head> + <!-- This tests a bug that can occur when content layer CSP is not told + about the CSP inherited from the parent document which leads to it not + applying it to content layer CSP checks (such as frame-src with + PlzNavigate on). + Also see crbug.com/778658. --> + <script src='/resources/testharness.js'></script> + <script src='/resources/testharnessreport.js'></script> +</head> +<body> + <script> + var t = async_test("iframe still inherits correct CSP"); + + window.onmessage = t.step_func_done(function(e) { + assert_equals(e.data, "frame-src"); + }); + + function doDocWrite() { + x = document.getElementById('x'); + x.location = ""; + + // While document.write is deprecated I did not find another way to reproduce + // the original exploit. + x.contentDocument.write( + '<script>window.addEventListener("securitypolicyviolation", function(e) {' + + ' window.top.postMessage(e.violatedDirective, "*");' + + '});</scr' + 'ipt>' + + '<iframe src="../support/fail.html"></iframe>' + ); + x.contentDocument.close(); + + var s = document.createElement('script'); + s.async = true; + s.defer = true; + s.src = '../support/checkReport.sub.js?reportField=violated-directive&reportValue=frame-src%20%27none%27'; + document.lastChild.appendChild(s); + } + </script> + <iframe id="x" onload="doDocWrite()" srcdoc="<a href='about:blank'>123</a>"></iframe> +</body> +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html.sub.headers b/testing/web-platform/tests/content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html.sub.headers new file mode 100644 index 0000000000..73fb991fb1 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html.sub.headers @@ -0,0 +1,5 @@ +Expires: Mon, 26 Jul 1997 05:00:00 GMT +Cache-Control: no-store, no-cache, must-revalidate +Pragma: no-cache +Set-Cookie: policy-inherited-correctly-by-plznavigate={{$id:uuid()}}; Path=/content-security-policy/generic/ +Content-Security-Policy: frame-src 'none'; script-src 'self' 'unsafe-inline'; report-uri /reporting/resources/report.py?op=put&reportID={{$id}} diff --git a/testing/web-platform/tests/content-security-policy/generic/positiveTest.js b/testing/web-platform/tests/content-security-policy/generic/positiveTest.js new file mode 100644 index 0000000000..15053e055d --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/positiveTest.js @@ -0,0 +1 @@ +window.cspPositiveTest = true; diff --git a/testing/web-platform/tests/content-security-policy/generic/support/304-response.py b/testing/web-platform/tests/content-security-policy/generic/support/304-response.py new file mode 100644 index 0000000000..f9756555f7 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/support/304-response.py @@ -0,0 +1,33 @@ +def main(request, response): + if request.headers.get(b"If-None-Match"): + # we are now receing the second request, we will send back a different CSP + # with the 304 response + response.status = 304 + headers = [(b"Content-Type", b"text/html"), + (b"Content-Security-Policy", b"script-src 'nonce-def' 'sha256-IIB78ZS1RMMrAWpsLg/RrDbVPhI14rKm3sFOeKPYulw=';"), + (b"Cache-Control", b"private, max-age=0, must-revalidate"), + (b"ETag", b"123456")] + return headers, u"" + else: + headers = [(b"Content-Type", b"text/html"), + (b"Content-Security-Policy", b"script-src 'nonce-abc' 'sha256-IIB78ZS1RMMrAWpsLg/RrDbVPhI14rKm3sFOeKPYulw=';"), + (b"Cache-Control", b"private, max-age=0, must-revalidate"), + (b"Etag", b"123456")] + return headers, u''' +<!DOCTYPE html> +<html> +<head> + <script> + window.addEventListener("securitypolicyviolation", function(e) { + top.postMessage(e.originalPolicy, '*'); + }); + </script> + <script nonce="abc"> + top.postMessage('abc_executed', '*'); + </script> + <script nonce="def"> + top.postMessage('def_executed', '*'); + </script> +</head> +</html> +''' diff --git a/testing/web-platform/tests/content-security-policy/generic/support/eval.js b/testing/web-platform/tests/content-security-policy/generic/support/eval.js new file mode 100644 index 0000000000..d8ba2a5589 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/support/eval.js @@ -0,0 +1,2 @@ +postMessage('unsafe-inline allowed'); +eval("postMessage('unsafe-eval allowed')"); diff --git a/testing/web-platform/tests/content-security-policy/generic/support/load_img_and_post_result_header.html b/testing/web-platform/tests/content-security-policy/generic/support/load_img_and_post_result_header.html new file mode 100644 index 0000000000..c7a2e75dba --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/support/load_img_and_post_result_header.html @@ -0,0 +1,11 @@ +<html> +<body> + <script> + var img = document.createElement("img"); + img.src = "/content-security-policy/support/pass.png"; + img.onload = function() { parent.postMessage('img loaded', '*'); } + img.onerror = function() { parent.postMessage('img not loaded', '*'); } + document.body.appendChild(img); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/support/load_img_and_post_result_header.html.sub.headers b/testing/web-platform/tests/content-security-policy/generic/support/load_img_and_post_result_header.html.sub.headers new file mode 100644 index 0000000000..e9bf21bab4 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/support/load_img_and_post_result_header.html.sub.headers @@ -0,0 +1 @@ +Content-Security-Policy: {{GET[csp]}} diff --git a/testing/web-platform/tests/content-security-policy/generic/support/load_img_and_post_result_meta.sub.html b/testing/web-platform/tests/content-security-policy/generic/support/load_img_and_post_result_meta.sub.html new file mode 100644 index 0000000000..ac0cf39dd0 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/support/load_img_and_post_result_meta.sub.html @@ -0,0 +1,14 @@ +<html> +<head> + <meta http-equiv="Content-Security-Policy" content="{{GET[csp]}}"> +</head> +<body> + <script> + var img = document.createElement("img"); + img.src = "/content-security-policy/support/pass.png"; + img.onload = function() { parent.postMessage('img loaded', '*'); } + img.onerror = function() { parent.postMessage('img not loaded', '*'); } + document.body.appendChild(img); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/content-security-policy/generic/support/log-pass.html b/testing/web-platform/tests/content-security-policy/generic/support/log-pass.html new file mode 100644 index 0000000000..4334ea4c66 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/support/log-pass.html @@ -0,0 +1,3 @@ +<script> + window.parent.postMessage('PASS', '*'); +</script> diff --git a/testing/web-platform/tests/content-security-policy/generic/support/sandboxed-eval.sub.html b/testing/web-platform/tests/content-security-policy/generic/support/sandboxed-eval.sub.html new file mode 100644 index 0000000000..9480e521de --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/support/sandboxed-eval.sub.html @@ -0,0 +1,4 @@ +<script> + window.parent.postMessage('PASS (1/2): Script can execute', '*'); + eval("window.parent.postMessage('PASS (2/2): Eval works', '*')"); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/content-security-policy/generic/support/sandboxed-eval.sub.html.sub.headers b/testing/web-platform/tests/content-security-policy/generic/support/sandboxed-eval.sub.html.sub.headers new file mode 100644 index 0000000000..c7e4e7cc5b --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/support/sandboxed-eval.sub.html.sub.headers @@ -0,0 +1 @@ +Content-Security-Policy: sandbox allow-scripts
\ No newline at end of file diff --git a/testing/web-platform/tests/content-security-policy/generic/test-case.sub.js b/testing/web-platform/tests/content-security-policy/generic/test-case.sub.js new file mode 100644 index 0000000000..d9a6494dd3 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/test-case.sub.js @@ -0,0 +1,98 @@ +function TestCase(scenarios, sanityChecker) { + function runTest(scenario) { + sanityChecker.checkScenario(scenario, subresourceMap); + + const urls = getRequestURLs(scenario.subresource, + scenario.origin, + scenario.redirection); + + /** @type {Subresource} */ + const subresource = { + subresourceType: scenario.subresource, + url: urls.testUrl, + policyDeliveries: scenario.subresource_policy_deliveries, + }; + + let violationEventResolve; + // Resolved with an array of securitypolicyviolation events. + const violationEventPromise = new Promise(resolve => { + violationEventResolve = resolve; + }); + + promise_test(async t => { + await xhrRequest(urls.announceUrl); + + // Currently only requests from top-level Documents are tested + // (specified by `spec.src.json`) and thus securitypolicyviolation + // events are assumed to be fired on the top-level Document here. + // When adding non-top-level Document tests, securitypolicyviolation + // events should be caught in appropriate contexts. + const violationEvents = []; + const listener = e => { violationEvents.push(e); }; + document.addEventListener('securitypolicyviolation', listener); + + try { + // Send out the real resource request. + // This should tear down the key if it's not blocked. + const mainPromise = invokeRequest(subresource, scenario.source_context_list); + if (scenario.expectation === 'allowed') { + await mainPromise; + } else { + await mainPromise + .then(t.unreached_func('main promise resolved unexpectedly')) + .catch(_ => {}); + } + } finally { + // Always perform post-processing/clean up for + // 'securitypolicyviolation' events and resolve + // `violationEventPromise`, to prevent timeout of the + // promise_test() below. + + // securitypolicyviolation events are fired in a queued task in + // https://w3c.github.io/webappsec-csp/#report-violation + // so wait for queued tasks to run using setTimeout(). + let timeout = 0; + if (scenario.subresource.startsWith('worklet-') && + navigator.userAgent.includes("Firefox/")) { + // https://bugzilla.mozilla.org/show_bug.cgi?id=1808911 + // In Firefox sometimes violations from Worklets are delayed. + timeout = 10; + } + await new Promise(resolve => setTimeout(resolve, timeout)); + + // Pass violation events to `violationEventPromise` (which will be tested + // in the subsequent promise_test()) and clean up the listener. + violationEventResolve(violationEvents); + document.removeEventListener('securitypolicyviolation', listener); + } + + // Send request to check if the key has been torn down. + const assertResult = await xhrRequest(urls.assertUrl); + + // Now check if the value has been torn down. If it's still there, + // we have blocked the request by content security policy. + assert_equals(assertResult.status, scenario.expectation, + "The resource request should be '" + scenario.expectation + "'."); + + }, scenario.test_description); + + promise_test(async _ => { + const violationEvents = await violationEventPromise; + if (scenario.expectation === 'allowed') { + assert_array_equals(violationEvents, [], + 'no violation events should be fired'); + } else { + assert_equals(violationEvents.length, 1, + 'One violation event should be fired'); + } + }, scenario.test_description + ": securitypolicyviolation"); + } // runTest + + function runTests() { + for (const scenario of scenarios) { + runTest(scenario); + } + } + + return {start: runTests}; +} diff --git a/testing/web-platform/tests/content-security-policy/generic/unreached.js b/testing/web-platform/tests/content-security-policy/generic/unreached.js new file mode 100644 index 0000000000..893fb5eba1 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/unreached.js @@ -0,0 +1,3 @@ +onload = function() { + t1.step(function() {assert_unreached("Script should not have ran.");}); +} diff --git a/testing/web-platform/tests/content-security-policy/generic/wildcardHostTest.js b/testing/web-platform/tests/content-security-policy/generic/wildcardHostTest.js new file mode 100644 index 0000000000..da3e2790f5 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/wildcardHostTest.js @@ -0,0 +1,8 @@ +wildcardHostTestRan = false; + +onload = function() { + test(function() { + assert_true(wildcardHostTestRan, 'Script should have ran.')}, + "Wildcard host matching works." + ); +} diff --git a/testing/web-platform/tests/content-security-policy/generic/wildcardHostTestFailure.js b/testing/web-platform/tests/content-security-policy/generic/wildcardHostTestFailure.js new file mode 100644 index 0000000000..75ec8cf80e --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/wildcardHostTestFailure.js @@ -0,0 +1,8 @@ +wildcardHostTestRan = false; + +onload = function() { + test(function() { + assert_false(wildcardHostTestRan, 'Script should not have ran.')}, + "Wildcard host matching works." + ); +} diff --git a/testing/web-platform/tests/content-security-policy/generic/wildcardHostTestSuceeds.js b/testing/web-platform/tests/content-security-policy/generic/wildcardHostTestSuceeds.js new file mode 100644 index 0000000000..8b115d7fc4 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/wildcardHostTestSuceeds.js @@ -0,0 +1 @@ +wildcardHostTestRan = true; diff --git a/testing/web-platform/tests/content-security-policy/generic/wildcardPortTest.js b/testing/web-platform/tests/content-security-policy/generic/wildcardPortTest.js new file mode 100644 index 0000000000..3cd1d2eaed --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/wildcardPortTest.js @@ -0,0 +1,8 @@ +wildcardPortTestRan = false; + +onload = function() { + test(function() { + assert_true(wildcardPortTestRan, 'Script should have ran.')}, + "Wildcard port matching works." + ); +} diff --git a/testing/web-platform/tests/content-security-policy/generic/wildcardPortTestSuceeds.js b/testing/web-platform/tests/content-security-policy/generic/wildcardPortTestSuceeds.js new file mode 100644 index 0000000000..0138deb2ee --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/generic/wildcardPortTestSuceeds.js @@ -0,0 +1 @@ +wildcardPortTestRan = true;
\ No newline at end of file |