Bug 992096 - Implement Sub Resource Integrity [2/2]. r=ckerschb
authorFrancois Marier <francois@mozilla.com>
Wed, 12 Aug 2015 20:19:16 -0700
changeset 257533 948b2e9d1fa282b3acd35a67e6b020b3e68510c7
parent 257532 bab5913ea6cbb558457670e1785b0296cc13acc0
child 257534 7d6edef7f2424f51be3b1539925c8caaea3effd7
push id29221
push userryanvm@gmail.com
push dateThu, 13 Aug 2015 14:43:44 +0000
treeherdermozilla-central@0cddd6a6565a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersckerschb
bugs992096
milestone43.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 992096 - Implement Sub Resource Integrity [2/2]. r=ckerschb Mochitests
dom/security/test/moz.build
dom/security/test/sri/iframe_script_crossdomain.html
dom/security/test/sri/iframe_script_sameorigin.html
dom/security/test/sri/iframe_sri_disabled.html
dom/security/test/sri/iframe_style_sameorigin.html
dom/security/test/sri/mochitest.ini
dom/security/test/sri/script.js
dom/security/test/sri/script.js^headers^
dom/security/test/sri/script_302.js
dom/security/test/sri/script_302.js^headers^
dom/security/test/sri/script_401.js
dom/security/test/sri/script_401.js^headers^
dom/security/test/sri/script_crossdomain1.js
dom/security/test/sri/script_crossdomain1.js^headers^
dom/security/test/sri/script_crossdomain2.js
dom/security/test/sri/script_crossdomain3.js
dom/security/test/sri/script_crossdomain3.js^headers^
dom/security/test/sri/script_crossdomain4.js
dom/security/test/sri/script_crossdomain4.js^headers^
dom/security/test/sri/style1.css
dom/security/test/sri/style2.css
dom/security/test/sri/style3.css
dom/security/test/sri/test_script_crossdomain.html
dom/security/test/sri/test_script_sameorigin.html
dom/security/test/sri/test_sri_disabled.html
dom/security/test/sri/test_style_sameorigin.html
--- a/dom/security/test/moz.build
+++ b/dom/security/test/moz.build
@@ -11,16 +11,17 @@ XPCSHELL_TESTS_MANIFESTS += [
 GeckoCppUnitTests([
      'TestCSPParser',
 ])
 
 MOCHITEST_MANIFESTS += [
     'cors/mochitest.ini',
     'csp/mochitest.ini',
     'mixedcontentblocker/mochitest.ini',
+    'sri/mochitest.ini',
 ]
 
 MOCHITEST_CHROME_MANIFESTS += [
     'csp/chrome.ini',
 ]
 
 BROWSER_CHROME_MANIFESTS += [
     'csp/browser.ini',
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/iframe_script_crossdomain.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML>
+<!-- Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html>
+<head>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+
+<script type="application/javascript">
+  SimpleTest.waitForExplicitFinish();
+
+  window.hasCORSLoaded = false;
+  window.hasNonCORSLoaded = false;
+
+  function good_nonsriLoaded() {
+    ok(true, "Non-eligible non-SRI resource was loaded correctly.");
+  }
+  function bad_nonsriBlocked() {
+    ok(false, "Non-eligible non-SRI resources should be loaded!");
+  }
+
+  function good_nonCORSInvalidLoaded() {
+    ok(true, "A non-CORS resource with invalid metadata was correctly loaded.");
+  }
+  function bad_nonCORSInvalidBlocked() {
+    ok(false, "Non-CORS resources with invalid metadata should be loaded!");
+  }
+
+  window.onerrorCalled = false;
+  window.onloadCalled = false;
+
+  function bad_onloadCalled() {
+    window.onloadCalled = true;
+  }
+
+  function good_onerrorCalled() {
+    window.onerrorCalled = true;
+  }
+
+  window.onload = function() {
+    SimpleTest.finish()
+  }
+</script>
+
+<!-- cors-enabled. should be loaded -->
+<script src="http://example.com/tests/dom/security/test/sri/script_crossdomain1.js"
+        crossorigin=""
+        integrity="sha512-9Tv2DL1fHvmPQa1RviwKleE/jq72jgxj8XGLyWn3H6Xp/qbtfK/jZINoPFAv2mf0Nn1TxhZYMFULAbzJNGkl4Q=="></script>
+
+<!-- not cors-enabled. should be blocked -->
+<script src="http://example.com/tests/dom/security/test/sri/script_crossdomain2.js"
+        crossorigin="anonymous"
+        integrity="sha256-ntgU2U1xv7HfK1XWMTSWz6vJkyVtGzMrIAxQkux1I94="
+        onload="bad_onloadCalled()"
+        onerror="good_onerrorCalled()"></script>
+
+<!-- non-cors but not actually using SRI. should trigger onload -->
+<script src="http://example.com/tests/dom/security/test/sri/script_crossdomain3.js"
+        integrity="    "
+        onload="good_nonsriLoaded()"
+        onerror="bad_nonsriBlocked()"></script>
+
+<!-- non-cors with invalid metadata. should trigger onload -->
+<script src="http://example.com/tests/dom/security/test/sri/script_crossdomain4.js"
+        integrity="sha256-bogus"
+        onload="good_nonCORSInvalidLoaded()"
+        onerror="bad_nonCORSInvalidBlocked()"></script>
+
+<script>
+  ok(window.hasCORSLoaded, "CORS-enabled resource with a correct hash");
+  ok(!window.hasNonCORSLoaded, "Correct hash, but non-CORS, should be blocked");
+  ok(!window.onloadCalled, "Failed loads should not call onload when they're cross-domain");
+  ok(window.onerrorCalled, "Failed loads should call onerror when they're cross-domain");
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/iframe_script_sameorigin.html
@@ -0,0 +1,209 @@
+<!DOCTYPE HTML>
+<!-- Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html>
+<head>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+    SimpleTest.waitForExplicitFinish();
+    window.onload = function() {
+      SimpleTest.finish();
+    }
+  </script>
+  <script>
+    function good_correctHashLoaded() {
+      ok(true, "A script was correctly loaded when integrity matched")
+    }
+    function bad_correctHashBlocked() {
+      ok(false, "We should load scripts with hashes that match!");
+    }
+
+    function good_correctHashArrayLoaded() {
+      ok(true, "A script was correctly loaded when one of the hashes in the integrity attribute matched")
+    }
+    function bad_correctHashArrayBlocked() {
+      ok(false, "We should load scripts with at least one hash that match!");
+    }
+
+    function good_emptyIntegrityLoaded() {
+      ok(true, "A script was correctly loaded when the integrity attribute was empty")
+    }
+    function bad_emptyIntegrityBlocked() {
+      ok(false, "We should load scripts with empty integrity attributes!");
+    }
+
+    function good_whitespaceIntegrityLoaded() {
+      ok(true, "A script was correctly loaded when the integrity attribute only contained whitespace")
+    }
+    function bad_whitespaceIntegrityBlocked() {
+      ok(false, "We should load scripts with integrity attributes containing only whitespace!");
+    }
+
+    function good_incorrectHashBlocked() {
+      ok(true, "A script was correctly blocked, because the hash digest was wrong");
+    }
+    function bad_incorrectHashLoaded() {
+      ok(false, "We should not load scripts with hashes that do not match the content!");
+    }
+
+    function good_incorrectHashArrayBlocked() {
+      ok(true, "A script was correctly blocked, because all the hashes were wrong");
+    }
+    function bad_incorrectHashArrayLoaded() {
+      ok(false, "We should not load scripts when none of the hashes match the content!");
+    }
+
+    function good_incorrectHashLengthBlocked() {
+      ok(true, "A script was correctly blocked, because the hash length was wrong");
+    }
+    function bad_incorrectHashLengthLoaded() {
+      ok(false, "We should not load scripts with hashes that don't have the right length!");
+    }
+
+    function bad_incorrectHashFunctionBlocked() {
+      ok(false, "We should load scripts with invalid/unsupported hash functions!");
+    }
+    function good_incorrectHashFunctionLoaded() {
+      ok(true, "A script was correctly loaded, despite the hash function being invalid/unsupported.");
+    }
+
+    function bad_missingHashFunctionBlocked() {
+      ok(false, "We should load scripts with missing hash functions!");
+    }
+    function good_missingHashFunctionLoaded() {
+      ok(true, "A script was correctly loaded, despite a missing hash function.");
+    }
+
+    function bad_missingHashValueBlocked() {
+      ok(false, "We should load scripts with missing hash digests!");
+    }
+    function good_missingHashValueLoaded() {
+      ok(true, "A script was correctly loaded, despite the missing hash digest.");
+    }
+
+    function good_401Blocked() {
+      ok(true, "A script was not loaded because of 401 response.");
+    }
+    function bad_401Loaded() {
+      ok(false, "We should nt load scripts with a 401 response!");
+    }
+
+    function good_valid302Loaded() {
+      ok(true, "A script was loaded successfully despite a 302 response.");
+    }
+    function bad_valid302Blocked() {
+      ok(false, "We should load scripts with a 302 response and the right hash!");
+    }
+
+    function good_invalid302Blocked() {
+      ok(true, "A script was blocked successfully after a 302 response.");
+    }
+    function bad_invalid302Loaded() {
+      ok(false, "We should not load scripts with a 302 response and the wrong hash!");
+    }
+  </script>
+</head>
+<body>
+  <!-- valid hash. should trigger onload -->
+  <!-- the hash value comes from running this command:
+       cat script.js | openssl dgst -sha256 -binary | openssl enc -base64 -A
+  -->
+  <script src="script.js"
+          integrity="sha256-RkrQYrxD/HCx+ImVLb51nvxJ6ZHfwuEm7bHppTun9oA="
+          onerror="bad_correctHashBlocked()"
+          onload="good_correctHashLoaded()"></script>
+
+  <!-- valid sha512 hash. should trigger onload -->
+  <script src="script.js"
+          integrity="sha512-mzSqH+vC6qrXX46JX2WEZ0FtY/lGj/5+5yYCBlk0jfYHLm0vP6XgsURbq83mwMApsnwbDLXdgjp5J8E93GT6Mw==?ignore=this"
+          onerror="bad_correctHashBlocked()"
+          onload="good_correctHashLoaded()"></script>
+
+  <!-- one valid sha256 hash. should trigger onload -->
+  <script src="script.js"
+          integrity="sha256-rkrQYrxD/HCx+ImVLb51nvxJ6ZHfwuEm7bHppTun9oA= sha256-RkrQYrxD/HCx+ImVLb51nvxJ6ZHfwuEm7bHppTun9oA= sha256-rkrQYrxD/HCx+ImVLb51nvxJ6ZHfwuEm7bHppTun9oA="
+          onerror="bad_correctHashArrayBlocked()"
+          onload="good_correctHashArrayLoaded()"></script>
+
+  <!-- empty integrity. should trigger onload -->
+  <script src="script.js"
+          integrity=""
+          onerror="bad_emptyIntegrityBlocked()"
+          onload="good_emptyIntegrityLoaded()"></script>
+
+  <!-- whitespace integrity. should trigger onload -->
+  <script src="script.js"
+          integrity="  
+	
+"
+          onerror="bad_whitespaceIntegrityBlocked()"
+          onload="good_whitespaceIntegrityLoaded()"></script>
+
+  <!-- invalid sha256 hash but valid sha384 hash. should trigger onload -->
+  <script src="script.js"
+          integrity="sha256-bogus sha384-zDCkvKOHXk8mM6Nk07oOGXGME17PA4+ydFw+hq0r9kgF6ZDYFWK3fLGPEy7FoOAo?"
+          onerror="bad_correctHashBlocked()"
+          onload="good_correctHashLoaded()"></script>
+
+  <!-- valid sha256 and invalid sha384. should trigger onerror -->
+  <script src="script.js"
+          integrity="sha256-RkrQYrxD/HCx+ImVLb51nvxJ6ZHfwuEm7bHppTun9oA= sha384-RkrQYrxD/HCx+ImVLb51nvxJ6ZHfwuEm7bHppTun9oA="
+          onerror="good_incorrectHashLengthBlocked()"
+          onload="bad_incorrectHashLengthLoaded()"></script>
+
+  <!-- invalid hash. should trigger onerror -->
+  <script src="script.js"
+          integrity="sha256-rkrQYrxD/HCx+ImVLb51nvxJ6ZHfwuEm7bHppTun9oA="
+          onerror="good_incorrectHashBlocked()"
+          onload="bad_incorrectHashLoaded()"></script>
+
+  <!-- invalid hashes. should trigger onerror -->
+  <script src="script.js"
+          integrity="sha256-rkrQYrxD/HCx+ImVLb51nvxJ6ZHfwuEm7bHppTun9oA= sha256-ZkrQYrxD/HCx+ImVLb51nvxJ6ZHfwuEm7bHppTun9oA= sha256-zkrQYrxD/HCx+ImVLb51nvxJ6ZHfwuEm7bHppTun9oA="
+          onerror="good_incorrectHashBlocked()"
+          onload="bad_incorrectHashLoaded()"></script>
+
+  <!-- invalid hash function. should trigger onload -->
+  <script src="script.js"
+          integrity="rot13-RkrQYrxD/HCx+ImVLb51nvxJ6ZHfwuEm7bHppTun9oA="
+          onerror="bad_incorrectHashFunctionBlocked()"
+          onload="good_incorrectHashFunctionLoaded()"></script>
+
+  <!-- missing hash function. should trigger onload -->
+  <script src="script.js"
+          integrity="RkrQYrxD/HCx+ImVLb51nvxJ6ZHfwuEm7bHppTun9oA="
+          onerror="bad_missingHashFunctionBlocked()"
+          onload="good_missingHashFunctionLoaded()"></script>
+
+  <!-- missing hash value. should trigger onload -->
+  <script src="script.js"
+          integrity="sha512-"
+          onerror="bad_missingHashValueBlocked()"
+          onload="good_missingHashValueLoaded()"></script>
+
+  <!-- 401 response. should trigger onerror -->
+  <script src="script_401.js"
+          integrity="sha256-RkrQYrxD/HCx+ImVLb51nvxJ6ZHfwuEm7bHppTun9oA="
+          onerror="good_401Blocked()"
+          onload="bad_401Loaded()"></script>
+
+  <!-- valid sha256 after a redirection. should trigger onload -->
+  <script src="script_302.js"
+          integrity="sha256-RkrQYrxD/HCx+ImVLb51nvxJ6ZHfwuEm7bHppTun9oA="
+          onerror="bad_valid302Blocked()"
+          onload="good_valid302Loaded()"></script>
+
+  <!-- invalid sha256 after a redirection. should trigger onerror -->
+  <script src="script_302.js"
+          integrity="sha256-JSi74NSN8WQNr9syBGmNg2APJp9PnHUO5ioZo5hmIiQ="
+          onerror="good_invalid302Blocked()"
+          onload="bad_invalid302Loaded()"></script>
+
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/iframe_sri_disabled.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML>
+<!-- Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html>
+<head>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+    SimpleTest.waitForExplicitFinish();
+    window.onload = function() {
+      SimpleTest.finish();
+    }
+  </script>
+  <script>
+    function good_correctHashLoaded() {
+      ok(true, "A script was correctly loaded when integrity matched")
+    }
+    function bad_correctHashBlocked() {
+      ok(false, "We should load scripts with hashes that match!");
+    }
+
+    function good_incorrectHashLoaded() {
+      ok(true, "A script was correctly loaded despite the incorrect hash because SRI is disabled.");
+    }
+    function bad_incorrectHashBlocked() {
+      ok(false, "We should load scripts with hashes that do not match the content when SRI is disabled!");
+    }
+
+    function good_correctStyleHashLoaded() {
+      ok(true, "A stylesheet was correctly loaded when integrity matched")
+    }
+    function bad_correctStyleHashBlocked() {
+      ok(false, "We should load stylesheets with hashes that match!");
+    }
+
+    function good_incorrectStyleHashLoaded() {
+      ok(true, "A stylesheet was correctly loaded despite the incorrect hash because SRI is disabled.");
+    }
+    function bad_incorrectStyleHashBlocked() {
+      ok(false, "We should load stylesheets with hashes that do not match the content when SRI is disabled!");
+    }
+  </script>
+
+  <!-- valid sha256 hash. should trigger onload -->
+  <link rel="stylesheet" href="style1.css?disabled"
+        integrity="sha256-qs8lnkunWoVldk5d5E+652yth4VTSHohlBKQvvgGwa8="
+        onerror="bad_correctStyleHashBlocked()"
+        onload="good_correctStyleHashLoaded()">
+
+  <!-- invalid sha256 hash. should trigger onerror -->
+  <link rel="stylesheet" href="style2.css?disabled"
+        integrity="sha256-bogus"
+        onerror="bad_incorrectStyleHashBlocked()"
+        onload="good_incorrectStyleHashLoaded()">
+</head>
+<body>
+  <!-- valid hash. should trigger onload -->
+  <script src="script.js"
+          integrity="sha256-RkrQYrxD/HCx+ImVLb51nvxJ6ZHfwuEm7bHppTun9oA="
+          onerror="bad_correctHashBlocked()"
+          onload="good_correctHashLoaded()"></script>
+
+  <!-- invalid hash. should trigger onerror -->
+  <script src="script.js"
+          integrity="sha256-rkrQYrxD/HCx+ImVLb51nvxJ6ZHfwuEm7bHppTun9oA="
+          onerror="bad_incorrectHashBlocked()"
+          onload="good_incorrectHashLoaded()"></script>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/iframe_style_sameorigin.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML>
+<!-- Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html>
+<head>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+    function check_styles() {
+      var redText = document.getElementById('red-text');
+      var blackText = document.getElementById('black-text');
+      var redTextColor = window.getComputedStyle(redText, null).getPropertyValue('color');
+      var blackTextColor = window.getComputedStyle(blackText, null).getPropertyValue('color');
+      ok(redTextColor == 'rgb(255, 0, 0)', "The first part should be red.");
+      ok(blackTextColor == 'rgb(0, 0, 0)', "The second part should still be black.");
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    window.onload = function() {
+      check_styles();
+      SimpleTest.finish();
+    }
+  </script>
+  <script>
+    function good_correctHashLoaded() {
+      ok(true, "A stylesheet was correctly loaded when integrity matched");
+    }
+    function bad_correctHashBlocked() {
+      ok(false, "We should load stylesheets with hashes that match!");
+    }
+
+    function good_emptyIntegrityLoaded() {
+      ok(true, "A stylesheet was correctly loaded when the integrity attribute was empty");
+    }
+    function bad_emptyIntegrityBlocked() {
+      ok(false, "We should load stylesheets with empty integrity attributes!");
+    }
+
+    function good_incorrectHashBlocked() {
+      ok(true, "A stylesheet was correctly blocked, because the hash digest was wrong");
+    }
+    function bad_incorrectHashLoaded() {
+      ok(false, "We should not load stylesheets with hashes that do not match the content!");
+    }
+  </script>
+
+  <!-- valid sha256 hash. should trigger onload -->
+  <link rel="stylesheet" href="style1.css"
+        integrity="sha256-qs8lnkunWoVldk5d5E+652yth4VTSHohlBKQvvgGwa8="
+        onerror="bad_correctHashBlocked()"
+        onload="good_correctHashLoaded()">
+
+  <!-- empty metadata. should trigger onload -->
+  <link rel="stylesheet" href="style2.css"
+        integrity=""
+        onerror="bad_emptyIntegrityBlocked()"
+        onload="good_emptyIntegrityLoaded()">
+
+  <!-- invalid sha256 hash. should trigger onerror -->
+  <link rel="stylesheet" href="style3.css"
+        integrity="sha256-bogus"
+        onerror="good_incorrectHashBlocked()"
+        onload="bad_incorrectHashLoaded()">
+</head>
+<body>
+<p><span id="red-text">This should be red </span> and
+  <span id="black-text">this should stay black.</p>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/mochitest.ini
@@ -0,0 +1,30 @@
+[DEFAULT]
+support-files =
+  iframe_script_crossdomain.html
+  iframe_script_sameorigin.html
+  iframe_sri_disabled.html
+  iframe_style_sameorigin.html
+  script_crossdomain1.js
+  script_crossdomain1.js^headers^
+  script_crossdomain2.js
+  script_crossdomain3.js
+  script_crossdomain3.js^headers^
+  script_crossdomain4.js
+  script_crossdomain4.js^headers^
+  script.js
+  script.js^headers^
+  script_302.js
+  script_302.js^headers^
+  script_401.js
+  script_401.js^headers^
+  style1.css
+  style2.css
+  style3.css
+
+[test_script_sameorigin.html]
+
+[test_script_crossdomain.html]
+
+[test_sri_disabled.html]
+
+[test_style_sameorigin.html]
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/script.js
@@ -0,0 +1,1 @@
+var load=true;
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/script.js^headers^
@@ -0,0 +1,1 @@
+Cache-control: public
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/script_302.js
@@ -0,0 +1,1 @@
+var load=false;
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/script_302.js^headers^
@@ -0,0 +1,2 @@
+HTTP 302 Found
+Location: /tests/dom/security/test/sri/script.js
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/script_401.js
@@ -0,0 +1,1 @@
+var load=true;
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/script_401.js^headers^
@@ -0,0 +1,2 @@
+HTTP 401 Authorization Required
+Cache-control: public
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/script_crossdomain1.js
@@ -0,0 +1,4 @@
+/*
+ * this file should be loaded, because it has CORS enabled.
+*/
+window.hasCORSLoaded = true;
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/script_crossdomain1.js^headers^
@@ -0,0 +1,1 @@
+Access-Control-Allow-Origin: http://mochi.test:8888
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/script_crossdomain2.js
@@ -0,0 +1,5 @@
+/*
+ * this file should not be loaded, because it does not have CORS
+ * enabled.
+ */
+window.hasNonCORSLoaded = true;
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/script_crossdomain3.js
@@ -0,0 +1,1 @@
+// This script intentionally left blank
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/script_crossdomain3.js^headers^
@@ -0,0 +1,1 @@
+Access-Control-Allow-Origin: http://mochi.test:8888
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/script_crossdomain4.js
@@ -0,0 +1,1 @@
+// This script intentionally left blank
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/script_crossdomain4.js^headers^
@@ -0,0 +1,1 @@
+Access-Control-Allow-Origin: http://mochi.test:8888
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/style1.css
@@ -0,0 +1,3 @@
+#red-text {
+  color: red;
+}
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/style2.css
@@ -0,0 +1,1 @@
+; A valid but somewhat uninteresting stylesheet
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/style3.css
@@ -0,0 +1,3 @@
+#black-text {
+  color: green;
+}
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/test_script_crossdomain.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<!-- Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Cross-domain script tests for Bug 992096</title>
+  <script>
+    SpecialPowers.setBoolPref("security.sri.enable", true);
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=992096">Mozilla Bug 992096</a>
+<div>
+  <iframe src="iframe_script_crossdomain.html" height="100%" width="90%" frameborder="0"></iframe>
+</div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/test_script_sameorigin.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<!-- Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Same-origin script tests for Bug 992096</title>
+  <script>
+    SpecialPowers.setBoolPref("security.sri.enable", true);
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=992096">Mozilla Bug 992096</a>
+<div>
+  <iframe src="iframe_script_sameorigin.html" height="100%" width="90%" frameborder="0"></iframe>
+</div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/test_sri_disabled.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<!-- Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>security.sri.enable tests for Bug 992096</title>
+  <script>
+    SpecialPowers.setBoolPref("security.sri.enable", false);
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=992096">Mozilla Bug 992096</a>
+<div>
+  <iframe src="iframe_sri_disabled.html" height="100%" width="90%" frameborder="0"></iframe>
+</div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/sri/test_style_sameorigin.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<!-- Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Same-origin stylesheet tests for Bug 992096</title>
+  <script>
+    SpecialPowers.setBoolPref("security.sri.enable", true);
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=992096">Mozilla Bug 992096</a>
+<div>
+  <iframe src="iframe_style_sameorigin.html" height="100%" width="90%" frameborder="0"></iframe>
+</div>
+</body>
+</html>