summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/subresource-integrity/subresource-integrity.sub.html
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/subresource-integrity/subresource-integrity.sub.html')
-rw-r--r--testing/web-platform/tests/subresource-integrity/subresource-integrity.sub.html573
1 files changed, 573 insertions, 0 deletions
diff --git a/testing/web-platform/tests/subresource-integrity/subresource-integrity.sub.html b/testing/web-platform/tests/subresource-integrity/subresource-integrity.sub.html
new file mode 100644
index 000000000..89ae018e4
--- /dev/null
+++ b/testing/web-platform/tests/subresource-integrity/subresource-integrity.sub.html
@@ -0,0 +1,573 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Subresource Integrity</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id="log"></div>
+
+<div id="container"></div>
+<script>
+ // This horrible hack is needed for the 'use-credentials' tests because, on
+ // response, if port 80 or 443 is the current port, it will not appear to
+ // the browser as part of the origin string. Since the origin *string* is
+ // used for CORS access control, instead of the origin itself, if there
+ // isn't an exact string match, the check will fail. For example,
+ // "http://example.com" would not match "http://example.com:80", because
+ // they are not exact string matches, even though the origins are the same.
+ //
+ // Thus, we only want the Access-Control-Allow-Origin header to have
+ // the port if it's not port 80 or 443, since the user agent will elide the
+ // ports in those cases.
+ var main_domain = "{{domains[]}}";
+ var www_domain = "{{domains[www]}}";
+ var default_port = "{{ports[http][0]}}";
+ if (location.protocol === "https:") {
+ default_port = "{{ports[https][0]}}";
+ }
+
+ var port_string = "";
+ if (default_port !== "80" && default_port !== "443")
+ port_string = ":" + default_port;
+
+ www_host_and_port = www_domain + port_string;
+
+ // <script> tests
+ var xorigin_anon_script = location.protocol
+ + '//' + www_host_and_port
+ + '/subresource-integrity/crossorigin-anon-script.js';
+
+ var xorigin_creds_script = location.protocol
+ + '//' + www_host_and_port
+ + '/subresource-integrity/crossorigin-creds-script.js?acao_port='
+ + port_string;
+
+ var xorigin_ineligible_script = location.protocol
+ + '//' + www_host_and_port
+ + '/subresource-integrity/crossorigin-ineligible-script.js';
+
+ var SRIScriptTest = function(pass, name, src, integrityValue, crossoriginValue) {
+ this.pass = pass;
+ this.name = "Script: " + name;
+ this.src = src;
+ this.integrityValue = integrityValue;
+ this.crossoriginValue = crossoriginValue;
+ }
+
+ SRIScriptTest.prototype.execute = function() {
+ var test = async_test(this.name);
+ var e = document.createElement("script");
+ e.src = this.src;
+ e.setAttribute("integrity", this.integrityValue);
+ if(this.crossoriginValue) {
+ e.setAttribute("crossorigin", this.crossoriginValue);
+ }
+ if(this.pass) {
+ e.addEventListener("load", function() {test.done()});
+ e.addEventListener("error", function() {
+ test.step(function(){ assert_unreached("Good load fired error handler.") })
+ });
+ } else {
+ e.addEventListener("load", function() {
+ test.step(function() { assert_unreached("Bad load succeeded.") })
+ });
+ e.addEventListener("error", function() {test.done()});
+ }
+ document.body.appendChild(e);
+ };
+
+ // Note that all of these style URLs have query parameters started, so any
+ // additional parameters should be appended starting with '&'.
+ var xorigin_anon_style = location.protocol
+ + '//' + www_host_and_port
+ + '/subresource-integrity/crossorigin-anon-style.css?';
+
+ var xorigin_creds_style = location.protocol
+ + '//' + www_host_and_port
+ + '/subresource-integrity/crossorigin-creds-style.css?acao_port='
+ + port_string;
+
+ var xorigin_ineligible_style = location.protocol
+ + '//' + www_host_and_port
+ + '/subresource-integrity/crossorigin-ineligible-style.css?';
+
+ // <link> tests
+ // Style tests must be done synchronously because they rely on the presence
+ // and absence of global style, which can affect later tests. Thus, instead
+ // of executing them one at a time, the style tests are implemented as a
+ // queue that builds up a list of tests, and then executes them one at a
+ // time.
+ var SRIStyleTest = function(queue, pass, name, attrs, customCallback, altPassValue) {
+ this.pass = pass;
+ this.name = "Style: " + name;
+ this.customCallback = customCallback || function () {};
+ this.attrs = attrs || {};
+ this.passValue = altPassValue || "rgb(255, 255, 0)";
+
+ this.test = async_test(this.name);
+
+ this.queue = queue;
+ this.queue.push(this);
+ }
+
+ SRIStyleTest.prototype.execute = function() {
+ var that = this;
+ var container = document.getElementById("container");
+ while (container.hasChildNodes()) {
+ container.removeChild(container.firstChild);
+ }
+
+ var test = this.test;
+
+ var div = document.createElement("div");
+ div.className = "testdiv";
+ var e = document.createElement("link");
+ this.attrs.rel = this.attrs.rel || "stylesheet";
+ for (var key in this.attrs) {
+ if (this.attrs.hasOwnProperty(key)) {
+ e.setAttribute(key, this.attrs[key]);
+ }
+ }
+
+ if(this.pass) {
+ e.addEventListener("load", function() {
+ test.step(function() {
+ var background = window.getComputedStyle(div, null).getPropertyValue("background-color");
+ assert_equals(background, that.passValue);
+ test.done();
+ });
+ });
+ e.addEventListener("error", function() {
+ test.step(function(){ assert_unreached("Good load fired error handler.") })
+ });
+ } else {
+ e.addEventListener("load", function() {
+ test.step(function() { assert_unreached("Bad load succeeded.") })
+ });
+ e.addEventListener("error", function() {
+ test.step(function() {
+ var background = window.getComputedStyle(div, null).getPropertyValue("background-color");
+ assert_not_equals(background, that.passValue);
+ test.done();
+ });
+ });
+ }
+ container.appendChild(div);
+ container.appendChild(e);
+ this.customCallback(e, container);
+ };
+
+ var style_tests = [];
+ style_tests.execute = function() {
+ if (this.length > 0) {
+ this.shift().execute();
+ }
+ }
+ add_result_callback(function(res) {
+ if (res.name.startsWith("Style: ")) {
+ style_tests.execute();
+ }
+ });
+
+ // Script tests
+ new SRIScriptTest(
+ true,
+ "Same-origin with correct sha256 hash.",
+ "matching-digest.js",
+ "sha256-U9WYDtBWkcHx13+9UKk/3Q5eoqDc4YGxYb07EPWzb9E="
+ ).execute();
+
+ new SRIScriptTest(
+ true,
+ "Same-origin with correct sha384 hash.",
+ "matching-digest.js",
+ "sha384-BDRTPSywZFyxfLEAzaLcL4FfERBgJgXfEkuT0r04LG93Yqn1PWNYPZMomaqEfE3H"
+ ).execute();
+
+ new SRIScriptTest(
+ true,
+ "Same-origin with correct sha512 hash.",
+ "matching-digest.js",
+ "sha512-geByvIIRspbnUnwooKGNNCb39nvg+EW0O9hDScTXeo/9pVZztLSUYU3LNV6H0lZapo8bCJUpyPPLAzE9fDzpxg=="
+ ).execute();
+
+ new SRIScriptTest(
+ true,
+ "Same-origin with empty integrity.",
+ "matching-digest.js",
+ ""
+ ).execute();
+
+ new SRIScriptTest(
+ false,
+ "Same-origin with incorrect hash.",
+ "non-matching-digest.js",
+ "sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead"
+ ).execute();
+
+ new SRIScriptTest(
+ true,
+ "Same-origin with multiple sha256 hashes, including correct.",
+ "matching-digest.js",
+ "sha256-U9WYDtBWkcHx13+9UKk/3Q5eoqDc4YGxYb07EPWzb9E= sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead"
+ ).execute();
+
+ new SRIScriptTest(
+ true,
+ "Same-origin with multiple sha256 hashes, including unknown algorithm.",
+ "matching-digest.js",
+ "sha256-U9WYDtBWkcHx13+9UKk/3Q5eoqDc4YGxYb07EPWzb9E= foo666-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead"
+ ).execute();
+
+ new SRIScriptTest(
+ true,
+ "Same-origin with sha256 mismatch, sha512 match",
+ "matching-digest.js",
+ "sha512-geByvIIRspbnUnwooKGNNCb39nvg+EW0O9hDScTXeo/9pVZztLSUYU3LNV6H0lZapo8bCJUpyPPLAzE9fDzpxg== sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead"
+ ).execute();
+
+ new SRIScriptTest(
+ false,
+ "Same-origin with sha256 match, sha512 mismatch",
+ "matching-digest.js",
+ "sha512-deadbeefspbnUnwooKGNNCb39nvg+EW0O9hDScTXeo/9pVZztLSUYU3LNV6H0lZapo8bCJUpyPPLAzE9fDzpxg== sha256-U9WYDtBWkcHx13+9UKk/3Q5eoqDc4YGxYb07EPWzb9E="
+ ).execute();
+
+ new SRIScriptTest(
+ true,
+ "<crossorigin='anonymous'> with correct hash, ACAO: *",
+ xorigin_anon_script,
+ "sha256-51AjITq701Y0yKSx3/UoIKtIY2UQ9+H8WGyyMuOWOC0=",
+ "anonymous"
+ ).execute();
+
+ new SRIScriptTest(
+ false,
+ "<crossorigin='anonymous'> with incorrect hash, ACAO: *",
+ xorigin_anon_script,
+ "sha256-deadbeefcSLlbFZCj1OACLxTxVck2TOrBTEdUbwz1yU=",
+ "anonymous"
+ ).execute();
+
+ new SRIScriptTest(
+ true,
+ "<crossorigin='use-credentials'> with correct hash, CORS-eligible",
+ xorigin_creds_script,
+ "sha256-IaGApVboXPQxVSm2wVFmhMq1Yu37gWklajgMdxKLIvc=",
+ "use-credentials"
+ ).execute();
+
+ new SRIScriptTest(
+ false,
+ "<crossorigin='use-credentials'> with incorrect hash CORS-eligible",
+ xorigin_creds_script,
+ "sha256-deadbeef2S+pTRZgiw3DWrhC6JLDlt2zRyGpwH7unU8=",
+ "use-credentials"
+ ).execute();
+
+ new SRIScriptTest(
+ false,
+ "<crossorigin='anonymous'> with CORS-ineligible resource",
+ xorigin_ineligible_script,
+ "sha256-F5fXKTX7SiWjtgybxiBZIo2qhh2WiQnNx372E60XrOo=",
+ "anonymous"
+ ).execute();
+
+ new SRIScriptTest(
+ false,
+ "Cross-origin, not CORS request, with correct hash",
+ xorigin_anon_script,
+ "sha256-51AjITq701Y0yKSx3/UoIKtIY2UQ9+H8WGyyMuOWOC0="
+ ).execute();
+
+ new SRIScriptTest(
+ false,
+ "Cross-origin, not CORS request, with hash mismatch",
+ xorigin_anon_script,
+ "sha256-deadbeef01Y0yKSx3/UoIKtIY2UQ9+H8WGyyMuOWOC0="
+ ).execute();
+
+ new SRIScriptTest(
+ true,
+ "Cross-origin, empty integrity",
+ xorigin_anon_script,
+ ""
+ ).execute();
+
+ new SRIScriptTest(
+ true,
+ "Same-origin with correct hash, options.",
+ "matching-digest.js",
+ "sha256-U9WYDtBWkcHx13+9UKk/3Q5eoqDc4YGxYb07EPWzb9E=?foo=bar?spam=eggs"
+ ).execute();
+
+ new SRIScriptTest(
+ true,
+ "Same-origin with unknown algorithm only.",
+ "matching-digest.js",
+ "foo666-U9WYDtBWkcHx13+9UKk/3Q5eoqDc4YGxYb07EPWzb9E="
+ ).execute();
+
+ // Style tests
+ new SRIStyleTest(
+ style_tests,
+ true,
+ "Same-origin with correct sha256 hash",
+ {
+ href: "style.css?1",
+ integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4="
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ true,
+ "Same-origin with correct sha384 hash",
+ {
+ href: "style.css?2",
+ integrity: "sha384-wDAWxH4tOWBwAwHfBn9B7XuNmFxHTMeigAMwn0iVQ0zq3FtmYMLxihcGnU64CwcX"
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ true,
+ "Same-origin with correct sha512 hash",
+ {
+ href: "style.css?3",
+ integrity: "sha512-9wXDjd6Wq3H6nPAhI9zOvG7mJkUr03MTxaO+8ztTKnfJif42laL93Be/IF6YYZHHF4esitVYxiwpY2HSZX4l6w=="
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ true,
+ "Same-origin with empty integrity",
+ {
+ href: "style.css?4",
+ integrity: ""
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ false,
+ "Same-origin with incorrect hash.",
+ {
+ href: "style.css?5",
+ integrity: "sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead"
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ true,
+ "Same-origin with multiple sha256 hashes, including correct.",
+ {
+ href: "style.css?6",
+ integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4= sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead"
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ true,
+ "Same-origin with multiple sha256 hashes, including unknown algorithm.",
+ {
+ href: "style.css?7",
+ integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4= foo666-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead"
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ true,
+ "Same-origin with sha256 mismatch, sha512 match",
+ {
+ href: "style.css?8",
+ integrity: "sha512-9wXDjd6Wq3H6nPAhI9zOvG7mJkUr03MTxaO+8ztTKnfJif42laL93Be/IF6YYZHHF4esitVYxiwpY2HSZX4l6w== sha256-deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead"
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ false,
+ "Same-origin with sha256 match, sha512 mismatch",
+ {
+ href: "style.css?9",
+ integrity: "sha512-deadbeef9wXDjd6Wq3H6nPAhI9zOvG7mJkUr03MTxaO+8ztTKnfJif42laL93Be/IF6YYZHHF4esitVYxiwpY2== sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4="
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ true,
+ "<crossorigin='anonymous'> with correct hash, ACAO: *",
+ {
+ href: xorigin_anon_style + '&1',
+ integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=",
+ crossorigin: "anonymous"
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ false,
+ "<crossorigin='anonymous'> with incorrect hash, ACAO: *",
+ {
+ href: xorigin_anon_style + '&2',
+ integrity: "sha256-deadbeefCzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk=",
+ crossorigin: "anonymous"
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ true,
+ "<crossorigin='use-credentials'> with correct hash, CORS-eligible",
+ {
+ href: xorigin_creds_style + '&1',
+ integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=",
+ crossorigin: "use-credentials"
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ false,
+ "<crossorigin='use-credentials'> with incorrect hash CORS-eligible",
+ {
+ href: xorigin_creds_style + '&2',
+ integrity: "sha256-deadbeefCzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk=",
+ crossorigin: "use-credentials"
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ false,
+ "<crossorigin='anonymous'> with CORS-ineligible resource",
+ {
+ href: xorigin_ineligible_style + '&1',
+ integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=",
+ crossorigin: "anonymous"
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ false,
+ "Cross-origin, not CORS request, with correct hash",
+ {
+ href: xorigin_anon_style + '&3',
+ integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4="
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ false,
+ "Cross-origin, not CORS request, with hash mismatch",
+ {
+ href: xorigin_anon_style + '&4',
+ integrity: "sha256-deadbeefCzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk="
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ true,
+ "Cross-origin, empty integrity",
+ {
+ href: xorigin_anon_style + '&5',
+ integrity: ""
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ true,
+ "Same-origin with correct hash, options.",
+ {
+ href: "style.css?10",
+ integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=?foo=bar?spam=eggs"
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ true,
+ "Same-origin with unknown algorithm only.",
+ {
+ href: "style.css?11",
+ integrity: "foo666-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=?foo=bar?spam=eggs"
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ true,
+ "Same-origin with correct sha256 hash, rel='stylesheet license'",
+ {
+ href: "style.css?12",
+ integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=",
+ rel: "stylesheet license"
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ true,
+ "Same-origin with correct sha256 hash, rel='license stylesheet'",
+ {
+ href: "style.css?13",
+ integrity: "sha256-CzHgdJ7wOccM8L89n4bhcJMz3F+SPLT7YZk7gyCWUV4=",
+ rel: "license stylesheet"
+ }
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ true,
+ "Same-origin with correct sha256 and sha512 hash, rel='alternate stylesheet' enabled",
+ {
+ href: "alternate.css?1",
+ title: "alt",
+ type: "text/css",
+ class: "alternate",
+ disabled: "disabled",
+ rel: "alternate stylesheet",
+ integrity: "sha256-phbz83bWhnLig+d2VPKrRrTRyhqoDRo1ruGqZLZ0= sha512-8OYEB7ktnzcb6h+kB9CUIuc8qvKIyLpygRJdQSEEycRy74dUsB+Yu9rSjpOPjRUblle8WWX9Gn7v39LK2Oceig==",
+ },
+ function (link, container) {
+ var alternate = document.querySelector('link.alternate');
+ alternate.disabled = false;
+ },
+ "rgb(255, 0, 0)"
+ );
+
+ new SRIStyleTest(
+ style_tests,
+ false,
+ "Same-origin with incorrect sha256 and sha512 hash, rel='alternate stylesheet' enabled",
+ {
+ href: "alternate.css?2",
+ title: "alt",
+ type: "text/css",
+ class: "alternate",
+ disabled: "disabled",
+ rel: "alternate stylesheet",
+ integrity: "sha256-fail83bWhnLig+d2VPKrRrTRyhqoDRo1ruGqZLZ0= sha512-failB7ktnzcb6h+kB9CUIuc8qvKIyLpygRJdQSEEycRy74dUsB+Yu9rSjpOPjRUblle8WWX9Gn7v39LK2Oceig==",
+ },
+ function (link, container) {
+ var alternate = document.querySelector('link.alternate');
+ alternate.disabled = false;
+ }
+ );
+
+ style_tests.execute();
+
+</script>
+<!-- TODO check cache-poisoned resources, transfer-encoding, 3xx redirect
+ to resource with matching hash, and cross-origin leakage test as in sec5.3.
+ -->