Bug 1299483 - CSP: Implement 'strict-dynamic', parser inserted mochitests. r=dveditz,freddyb
authorChristoph Kerschbaumer <ckerschb@christophkerschbaumer.com>
Tue, 08 Nov 2016 13:33:58 +0100
changeset 321522 201b2637eac61fc6bc85604c2d202f4c5b79e568
parent 321521 a802f55a2d95cb550b3f6e7a79399a8eae35d5e9
child 321523 f3c84b1049871fcbf39298d22411ecbc8b3ba8dd
push id83632
push usermozilla@christophkerschbaumer.com
push dateTue, 08 Nov 2016 15:52:17 +0000
treeherdermozilla-inbound@f3c84b104987 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdveditz, freddyb
bugs1299483
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1299483 - CSP: Implement 'strict-dynamic', parser inserted mochitests. r=dveditz,freddyb
dom/security/test/csp/file_strict_dynamic_non_parser_inserted.html
dom/security/test/csp/file_strict_dynamic_non_parser_inserted_inline.html
dom/security/test/csp/file_strict_dynamic_parser_inserted_doc_write.html
dom/security/test/csp/file_strict_dynamic_parser_inserted_doc_write_correct_nonce.html
dom/security/test/csp/file_strict_dynamic_unsafe_eval.html
dom/security/test/csp/mochitest.ini
dom/security/test/csp/test_strict_dynamic_parser_inserted.html
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/file_strict_dynamic_non_parser_inserted.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Bug 1299483 - CSP: Implement 'strict-dynamic'</title>
+</head>
+<body>
+<div id="testdiv">blocked</div>
+
+<script nonce="foo">
+  // generates a *non* parser inserted script and should be allowed
+  var myScript = document.createElement('script');
+  myScript.src = 'http://example.com/tests/dom/security/test/csp/file_strict_dynamic.js';
+  document.head.appendChild(myScript);
+</script>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/file_strict_dynamic_non_parser_inserted_inline.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Bug 1299483 - CSP: Implement 'strict-dynamic'</title>
+</head>
+<body>
+<div id="testdiv">blocked</div>
+
+<script nonce="foo">
+  var dynamicScript = document.createElement('script');
+  dynamicScript.textContent = 'document.getElementById("testdiv").textContent="allowed"';
+  document.head.appendChild(dynamicScript);
+</script>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/file_strict_dynamic_parser_inserted_doc_write.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Bug 1299483 - CSP: Implement 'strict-dynamic'</title>
+</head>
+<body>
+<div id="testdiv">blocked</div>
+
+<script nonce="foo">
+  // generates a parser inserted script and should be blocked
+  document.write("<script src='http://example.com/tests/dom/security/test/csp/file_strict_dynamic.js'><\/script>");
+</script>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/file_strict_dynamic_parser_inserted_doc_write_correct_nonce.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Bug 1299483 - CSP: Implement 'strict-dynamic'</title>
+</head>
+<body>
+<div id="testdiv">blocked</div>
+
+<script nonce="foo">
+  // generates a parser inserted script with a valid nonce- and should be allowed
+  document.write("<script nonce='foo' src='http://example.com/tests/dom/security/test/csp/file_strict_dynamic.js'><\/script>");
+</script>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/file_strict_dynamic_unsafe_eval.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Bug 1299483 - CSP: Implement 'strict-dynamic'</title>
+</head>
+<body>
+<div id="testdiv">blocked</div>
+
+<script nonce="foo">
+  eval('document.getElementById("testdiv").innerHTML = "allowed";');
+</script>
+
+</body>
+</html>
\ No newline at end of file
--- a/dom/security/test/csp/mochitest.ini
+++ b/dom/security/test/csp/mochitest.ini
@@ -187,16 +187,21 @@ support-files =
   file_require_sri_meta.js
   file_sendbeacon.html
   file_upgrade_insecure_docwrite_iframe.sjs
   file_data-uri_blocked.html
   file_data-uri_blocked.html^headers^
   file_strict_dynamic_script_inline.html
   file_strict_dynamic_script_extern.html
   file_strict_dynamic.js
+  file_strict_dynamic_parser_inserted_doc_write.html
+  file_strict_dynamic_parser_inserted_doc_write_correct_nonce.html
+  file_strict_dynamic_non_parser_inserted.html
+  file_strict_dynamic_non_parser_inserted_inline.html
+  file_strict_dynamic_unsafe_eval.html
 
 [test_base-uri.html]
 [test_blob_data_schemes.html]
 [test_connect-src.html]
 [test_CSP.html]
 [test_allow_https_schemes.html]
 [test_bug663567.html]
 [test_bug802872.html]
@@ -271,8 +276,9 @@ tags = mcb
 [test_sandbox.html]
 [test_ping.html]
 [test_require_sri_meta.html]
 [test_sendbeacon.html]
 [test_upgrade_insecure_docwrite_iframe.html]
 [test_bug1242019.html]
 [test_bug1312272.html]
 [test_strict_dynamic.html]
+[test_strict_dynamic_parser_inserted.html]
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/test_strict_dynamic_parser_inserted.html
@@ -0,0 +1,95 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Bug 1299483 - CSP: Implement 'strict-dynamic'</title>
+  <!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+  <iframe style="width:100%;" id="testframe"></iframe>
+
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.setBoolPref("security.csp.enableStrictDynamic", true);
+
+/* Description of the test:
+ * We loader parser and non parser inserted scripts making sure that
+ * parser inserted scripts are blocked if strict-dynamic is present
+ * and no valid nonce and also making sure that non-parser inserted
+ * scripts are allowed to execute.
+ */
+
+var tests = [
+  {
+    desc: "(parser inserted script) using doc.write(<script>) should be blocked",
+    result: "blocked",
+    file: "file_strict_dynamic_parser_inserted_doc_write.html",
+    policy: "script-src 'strict-dynamic' 'nonce-foo' http:"
+  },
+  {
+    desc: "(parser inserted script with valid nonce) using doc.write(<script>) should be allowed",
+    result: "allowed",
+    file: "file_strict_dynamic_parser_inserted_doc_write_correct_nonce.html",
+    policy: "script-src 'strict-dynamic' 'nonce-foo' https:"
+  },
+  {
+    desc: "(non parser inserted script) using appendChild() should allow external script",
+    result: "allowed",
+    file: "file_strict_dynamic_non_parser_inserted.html",
+    policy: "script-src 'strict-dynamic' 'nonce-foo' https:"
+  },
+  {
+     desc: "(non parser inserted script) using appendChild() should allow inline script",
+     result: "allowed",
+     file: "file_strict_dynamic_non_parser_inserted_inline.html",
+     policy: "script-src 'strict-dynamic' 'nonce-foo' https:"
+  },
+  {
+     desc: "strict-dynamic should not invalidate 'unsafe-eval'",
+     result: "allowed",
+     file: "file_strict_dynamic_unsafe_eval.html",
+     policy: "script-src 'strict-dynamic' 'nonce-foo' 'unsafe-eval'"
+   },
+];
+
+var counter = 0;
+var curTest;
+
+function loadNextTest() {
+  if (counter == tests.length) {
+    SimpleTest.finish();
+    return;
+  }
+
+  curTest = tests[counter++];
+  var src = "file_testserver.sjs?file=";
+  // append the file that should be served
+  src += escape("tests/dom/security/test/csp/" + curTest.file)
+  // append the CSP that should be used to serve the file
+  src += "&csp=" + escape(curTest.policy);
+
+  document.getElementById("testframe").addEventListener("load", test, false);
+  document.getElementById("testframe").src = src;
+}
+
+function test() {
+  try {
+    document.getElementById("testframe").removeEventListener('load', test, false);
+    var testframe = document.getElementById("testframe");
+    var divcontent = testframe.contentWindow.document.getElementById('testdiv').innerHTML;
+    is(divcontent, curTest.result, curTest.desc);
+  }
+  catch (e) {
+    ok(false, "ERROR: could not access content for test: '" + curTest.desc + "'");
+  }
+  loadNextTest();
+}
+
+// start running the tests
+loadNextTest();
+
+</script>
+</body>
+</html>