Bug 992096 - Implement Sub Resource Integrity [2/2] draft
authorFrancois Marier <francois@mozilla.com>
Tue, 09 Jun 2015 23:01:05 +1200
changeset 270707 f5a77373d311323fb41a71840dda35b8c8e12da9
parent 270629 e10e2e8d8bf22ee704d8b6f748a025fed5dd6ac2
child 270708 af296e77bece6484363835efe9e542b8ea7e66ff
push id2690
push userfmarier@mozilla.com
push dateTue, 09 Jun 2015 11:26:57 +0000
bugs992096
milestone41.0a1
Bug 992096 - Implement Sub Resource Integrity [2/2] Mochitests
dom/base/test/moz.build
dom/base/test/sri/iframe_script_crossdomain.html
dom/base/test/sri/iframe_script_sameorigin.html
dom/base/test/sri/iframe_sri_disabled.html
dom/base/test/sri/iframe_style_sameorigin.html
dom/base/test/sri/mochitest.ini
dom/base/test/sri/script.js
dom/base/test/sri/script.js^headers^
dom/base/test/sri/script_401.js
dom/base/test/sri/script_401.js^headers^
dom/base/test/sri/script_crossdomain1.js
dom/base/test/sri/script_crossdomain1.js^headers^
dom/base/test/sri/script_crossdomain2.js
dom/base/test/sri/script_crossdomain3.js
dom/base/test/sri/script_crossdomain3.js^headers^
dom/base/test/sri/script_crossdomain4.js
dom/base/test/sri/script_crossdomain4.js^headers^
dom/base/test/sri/style1.css
dom/base/test/sri/style2.css
dom/base/test/sri/style3.css
dom/base/test/sri/test_script_crossdomain.html
dom/base/test/sri/test_script_sameorigin.html
dom/base/test/sri/test_sri_disabled.html
dom/base/test/sri/test_style_sameorigin.html
--- a/dom/base/test/moz.build
+++ b/dom/base/test/moz.build
@@ -16,16 +16,17 @@ GeckoCppUnitTests([
     'TestPlainTextSerializer',
 ])
 
 MOCHITEST_MANIFESTS += [
     'chrome/mochitest.ini',
     'csp/mochitest.ini',
     'mixedcontentblocker/mochitest.ini',
     'mochitest.ini',
+    'sri/mochitest.ini',
     'websocket_hybi/mochitest.ini',
 ]
 # OOP tests don't work on Windows (bug 763081) or native-fennec
 # (see Bug 774939). App permission checks are also disabled on
 # anything but B2G (Bug 900707).
 if CONFIG['MOZ_CHILD_PERMISSIONS']:
     MOCHITEST_MANIFESTS += [
         'mochitest-child-permissions.ini',
new file mode 100644
--- /dev/null
+++ b/dom/base/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/base/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/base/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/base/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/base/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/base/test/sri/iframe_script_sameorigin.html
@@ -0,0 +1,182 @@
+<!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!");
+    }
+  </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>
+<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/base/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/base/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/base/test/sri/mochitest.ini
@@ -0,0 +1,28 @@
+[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_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/base/test/sri/script.js
@@ -0,0 +1,1 @@
+var load=true;
new file mode 100644
--- /dev/null
+++ b/dom/base/test/sri/script.js^headers^
@@ -0,0 +1,1 @@
+Cache-control: public
new file mode 100644
--- /dev/null
+++ b/dom/base/test/sri/script_401.js
@@ -0,0 +1,1 @@
+var load=true;
new file mode 100644
--- /dev/null
+++ b/dom/base/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/base/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/base/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/base/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/base/test/sri/script_crossdomain3.js
@@ -0,0 +1,1 @@
+// This script intentionally left blank
new file mode 100644
--- /dev/null
+++ b/dom/base/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/base/test/sri/script_crossdomain4.js
@@ -0,0 +1,1 @@
+// This script intentionally left blank
new file mode 100644
--- /dev/null
+++ b/dom/base/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/base/test/sri/style1.css
@@ -0,0 +1,3 @@
+#red-text {
+  color: red;
+}
new file mode 100644
--- /dev/null
+++ b/dom/base/test/sri/style2.css
@@ -0,0 +1,1 @@
+; A valid but somewhat uninteresting stylesheet
new file mode 100644
--- /dev/null
+++ b/dom/base/test/sri/style3.css
@@ -0,0 +1,3 @@
+#black-text {
+  color: green;
+}
new file mode 100644
--- /dev/null
+++ b/dom/base/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/base/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/base/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/base/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>