summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/content-security-policy/generic
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/tests/content-security-policy/generic
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/content-security-policy/generic')
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/304-response-should-update-csp.sub.html52
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/cspro-not-enforced-in-worker.html22
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/cspro-not-enforced-in-worker.html.sub.headers1
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/directive-name-case-insensitive.sub.html32
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/duplicate-directive.sub.html27
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/eval-typecheck-callout-order.tentative.html28
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/eval-typecheck-callout-order.tentative.html.headers1
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/fail-0_1.js3
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/filesystem-urls-do-not-match-self.sub.html60
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/filesystem-urls-match-filesystem.sub.html57
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/generic-0_1-img-src.html38
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/generic-0_1-script-src.html38
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/generic-0_10.sub.html27
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/generic-0_10_1.sub.html26
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/generic-0_2.html28
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/generic-0_2_2.sub.html26
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/generic-0_2_3.html26
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/generic-0_8.sub.html27
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/generic-0_8_1.sub.html31
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/generic-0_9.sub.html27
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/invalid-characters-in-policy.html75
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/negativeTests.js3
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/no-default-src.sub.html41
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/no-default-src.sub.html.sub.headers6
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/only-valid-whitespaces-are-allowed.html67
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/pass-0_1.js3
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/policy-does-not-affect-child.sub.html24
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html43
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/policy-inherited-correctly-by-plznavigate.html.sub.headers5
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/positiveTest.js1
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/src-trailing-dot.sub.any.js6
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/src-trailing-dot.sub.any.js.sub.headers1
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/support/304-response.py33
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/support/eval.js2
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/support/load_img_and_post_result_header.html11
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/support/load_img_and_post_result_header.html.sub.headers1
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/support/load_img_and_post_result_meta.sub.html14
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/support/log-pass.html3
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/support/sandboxed-eval.sub.html4
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/support/sandboxed-eval.sub.html.sub.headers1
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/test-case.sub.js98
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/unreached.js3
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/wildcardHostTest.js8
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/wildcardHostTestFailure.js8
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/wildcardHostTestSuceeds.js1
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/wildcardPortTest.js8
-rw-r--r--testing/web-platform/tests/content-security-policy/generic/wildcardPortTestSuceeds.js1
47 files changed, 1048 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 &apos;self&apos; or &apos;*&apos; 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 &apos;self&apos; or &apos;*&apos; 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,iVBORw0KGgoAAAANSUhEUgAAAKgAAABACAIAAAABPqsMAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1QoMCC8h3if5rgAAAB10RVh0Q29tbWVudABDcmVhdGVkIHdpdGggVGhlIEdJTVDvZCVuAAAGD0lEQVR42u2aa0yTVxiA39ILxa4KIkKrVCCIitzrqkAXQiXDSFjQHyZDBRRdtoDzgooao5uaoInID4hRJFC8RBOzxQuKigyYokuDSB0WlaJQlQrITRCwte1+nKVhpbT9aGUue59fb84573dO+uR7v/drS4OfAPkf4oQfAYpHUDyC4hEUj6B4BMUjKB5B8QiKR1A8guIRFI+geATFIygeQfEIikdQPEIVxmd1GsN+w9hBrV7bN9Kn7FHWqmqLHxY3vW2ycIWtS7Yeiz9G4h0VO47eO2rj1p4cz7WhayW+kuCZwdNdpjsznIe0Q53vO1X9qsbOxrr2uprWmrb+Nofn/lvQPqs/W5oVb0KBrCDrVpZGpzE7++iHR8Ezg0ms6FIsPL7Qho+Ali3O3h+zn81gW1n5M82BuVjqqZEpyjyVeMrs1CL+IqN1AAj0CBTNElm9YGFiYc7SHKvmHJ6Lpd7K/cF0YvK5/KV+S3eLd/tP9weAlNAUaYO0qrXKJGtd2DoS6A16J5oTGZG9llnYKDEgcUPEBhI/636WL8uvelHV1t82rB1mM9geHA8fV58QzxAhTxjjE+PAXCz15ku92cLIZXFr1tWEe4UDwLk/z635dc3oWWe6s3q72o3tBgD7qvYdiD0AAH0jfbxc3sjHkfF2LF9dvsx/GQDcbLmZdCHJwkrH5mKpp8CAZiC7IpvEUd5RJrMrFqwg1pU9ykO/H2rpbQEAV7brygUrLVxz8ezFJNh2cxtVc/bkonhq3Ht5jwReX3iNV+elDVIDGKQNUpNxs0x1nkoCZY+S6mHsyUXxE30oGP7R/3tP9Y7ziyNP91J5KQCUNpTqDXoAkPhKBNME412ne6ibBEEzg6iewZ5cFE8NY4XveN8xejw1LJV0cxXPK169ewUAL9+9vP38NgA40ZxSQ1OtlpDCxMI50+ZMrPxMIBfFU4DD5ByOO2zyoRPSwtJIUPyw2DhojNPC0mhg/jU67488AxgAQMgTNv/YfPXbq5miTNEskQvDxep57MnFrt56V890YvK4vFif2D1f7QlwDyCDcafjKl9UkjhmTkx1WjUA9Az38HP5H3Qfxvb5saWx1a3VZjfdsmRL7te5pGAY0Rl0ii7FnbY7l55cqnxRSZ4ajs1F8WbEW8bkXU6aJCXFvEBWsKl80+iVBcsLMr7MAIDT8tOpl8Yt+JGzIw9KDkp8JWYLg7JHmXUr68rTKw7PRfEUxJ98cHJz+Wbjbc1lcdXb1RwmBwCEhcJ6df3oxUKesO67OgAY0g55HfUa0AxYuLJgmmD53OVigTiCFxHgHkCn0UfP7rq960jtkU+Ri+LH/ZGmf6S/pbelVlVb0lDS2Nk4ejY9PL3omyIAkHfIw06EjU2Xfy8P8QwBgI1XNxbVF9l4EheGi5AvTJibkB6R7jHFAwAMYBAXi016C4fn4jPe1p807q6/G+0dbWMTHl0cTfVIbmy3suQy8jZxUXFx1cVVk5OLXb0lAtwDbLROXgWNvaHt9I70ZlzPILFYIJ60XBRvCcvfytm/ntDU9fc/AEjdnrTcTwrjv2udTqOnhKaQOOlC0uWnl8dbmTA3oSy5DABSQlP2/rZXZ9BR2mjejHkksNwbOjwX73jzxPvH87l8AOh433Gt+ZqFlTeUN9SDagDgc/nx/vGUdpnCnJIXn0fiB+0PJi0X73jrdfvso7Mf9R8trNQZdGfkZ3ZG7yRZ15uvG6dUW1W1qtp6db2iS9HW36YeUA9qBrV6LYfJ8XPzk/hKMkWZfm5+ZLHJS4E9udjVT7Crd3dxb89qZ9FZABB0POhx12PL6+fPmN+U0QQAGp2Gn8vvHu6m9JWR2bbcnlws9RNkdchqYl32WmbVOgA8efvk/qv7AMCis5KDkyntpdFpcu7mJP+SPIFz2pOLpd5SnS9pKLExpeRhSeTsSABYH74+X5ZPBgV5gijvqAheRKBHoI+rD4/L47K4TDpzWDv8ZvCNoktR3Vp9vvF8+0D72Avak4ulHsFSj6B4BMUjKB5B8QiKR1A8guIRFI+geATFo3gExSMoHkHxCIpHUDyC4hEUj6B45HPmL9so2ZKs94sNAAAAAElFTkSuQmCC'>
+ <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/src-trailing-dot.sub.any.js b/testing/web-platform/tests/content-security-policy/generic/src-trailing-dot.sub.any.js
new file mode 100644
index 0000000000..f2b45a6957
--- /dev/null
+++ b/testing/web-platform/tests/content-security-policy/generic/src-trailing-dot.sub.any.js
@@ -0,0 +1,6 @@
+// META: global=window,worker
+
+promise_test(t => {
+ return fetch("{{location[scheme]}}://{{host}}.:{{location[port]}}"
+ + "/content-security-policy/support/resource.py");
+}, "Fetch from host with trailing dot should be allowed by CSP.");
diff --git a/testing/web-platform/tests/content-security-policy/generic/src-trailing-dot.sub.any.js.sub.headers b/testing/web-platform/tests/content-security-policy/generic/src-trailing-dot.sub.any.js.sub.headers
new file mode 100644
index 0000000000..4a8ad9c0f5
--- /dev/null
+++ b/testing/web-platform/tests/content-security-policy/generic/src-trailing-dot.sub.any.js.sub.headers
@@ -0,0 +1 @@
+Content-Security-Policy: connect-src {{location[scheme]}}://{{host}}.:{{location[port]}} \ No newline at end of file
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