summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/fetch/nosniff
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/fetch/nosniff')
-rw-r--r--testing/web-platform/tests/fetch/nosniff/image.html39
-rw-r--r--testing/web-platform/tests/fetch/nosniff/importscripts.html14
-rw-r--r--testing/web-platform/tests/fetch/nosniff/importscripts.js28
-rw-r--r--testing/web-platform/tests/fetch/nosniff/parsing-nosniff.window.js27
-rw-r--r--testing/web-platform/tests/fetch/nosniff/resources/css.py23
-rw-r--r--testing/web-platform/tests/fetch/nosniff/resources/image.py24
-rw-r--r--testing/web-platform/tests/fetch/nosniff/resources/js.py17
-rw-r--r--testing/web-platform/tests/fetch/nosniff/resources/nosniff.py11
-rw-r--r--testing/web-platform/tests/fetch/nosniff/resources/worker.py16
-rw-r--r--testing/web-platform/tests/fetch/nosniff/resources/x-content-type-options.json62
-rw-r--r--testing/web-platform/tests/fetch/nosniff/script.html43
-rw-r--r--testing/web-platform/tests/fetch/nosniff/stylesheet.html60
-rw-r--r--testing/web-platform/tests/fetch/nosniff/worker.html28
13 files changed, 392 insertions, 0 deletions
diff --git a/testing/web-platform/tests/fetch/nosniff/image.html b/testing/web-platform/tests/fetch/nosniff/image.html
new file mode 100644
index 0000000000..9dfdb94cf6
--- /dev/null
+++ b/testing/web-platform/tests/fetch/nosniff/image.html
@@ -0,0 +1,39 @@
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+ // Note: images get always sniffed, nosniff doesn't do anything
+ // (but note the tentative Cross-Origin Read Blocking (CORB) tests
+ // - for example wpt/fetch/corb/img-mime-types-coverage.tentative.sub.html).
+ var passes = [
+ // Empty or non-sensical MIME types
+ null, "", "x", "x/x",
+
+ // Image MIME types
+ "image/gif", "image/png", "image/png;blah", "image/svg+xml",
+
+ // CORB-protected MIME types (but note that CORB doesn't apply here,
+ // because CORB ignores same-origin requests).
+ "text/html", "application/xml", "application/blah+xml"
+ ]
+
+ const get_url = (mime) => {
+ let url = "resources/image.py"
+ if (mime != null) {
+ url += "?type=" + encodeURIComponent(mime)
+ }
+ return url
+ }
+
+ passes.forEach(function(mime) {
+ async_test(function(t) {
+ var img = document.createElement("img")
+ img.onerror = t.unreached_func("Unexpected error event")
+ img.onload = t.step_func_done(function(){
+ assert_equals(img.width, 96)
+ })
+ img.src = get_url(mime)
+ document.body.appendChild(img)
+ }, "URL query: " + mime)
+ })
+</script>
diff --git a/testing/web-platform/tests/fetch/nosniff/importscripts.html b/testing/web-platform/tests/fetch/nosniff/importscripts.html
new file mode 100644
index 0000000000..920b6bdd40
--- /dev/null
+++ b/testing/web-platform/tests/fetch/nosniff/importscripts.html
@@ -0,0 +1,14 @@
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+ async_test(function(t) {
+ var w = new Worker("importscripts.js")
+ w.onmessage = t.step_func(function(e) {
+ if(e.data == "END")
+ t.done()
+ else
+ assert_equals(e.data, "PASS")
+ })
+ }, "Test importScripts()")
+</script>
diff --git a/testing/web-platform/tests/fetch/nosniff/importscripts.js b/testing/web-platform/tests/fetch/nosniff/importscripts.js
new file mode 100644
index 0000000000..18952805bb
--- /dev/null
+++ b/testing/web-platform/tests/fetch/nosniff/importscripts.js
@@ -0,0 +1,28 @@
+// Testing importScripts()
+function log(w) { this.postMessage(w) }
+function f() { log("FAIL") }
+function p() { log("PASS") }
+
+const get_url = (mime, outcome) => {
+ let url = "resources/js.py"
+ if (mime != null) {
+ url += "?type=" + encodeURIComponent(mime)
+ }
+ if (outcome) {
+ url += "&outcome=p"
+ }
+ return url
+}
+
+[null, "", "x", "x/x", "text/html", "text/json"].forEach(function(mime) {
+ try {
+ importScripts(get_url(mime))
+ } catch(e) {
+ (e.name == "NetworkError") ? p() : log("FAIL (no NetworkError exception): " + mime)
+ }
+
+})
+importScripts(get_url("text/javascript", true))
+importScripts(get_url("text/ecmascript", true))
+importScripts(get_url("text/ecmascript;blah", true))
+log("END")
diff --git a/testing/web-platform/tests/fetch/nosniff/parsing-nosniff.window.js b/testing/web-platform/tests/fetch/nosniff/parsing-nosniff.window.js
new file mode 100644
index 0000000000..2a2648653c
--- /dev/null
+++ b/testing/web-platform/tests/fetch/nosniff/parsing-nosniff.window.js
@@ -0,0 +1,27 @@
+promise_test(() => fetch("resources/x-content-type-options.json").then(res => res.json()).then(runTests), "Loading JSONā€¦");
+
+function runTests(allTestData) {
+ for (let i = 0; i < allTestData.length; i++) {
+ const testData = allTestData[i],
+ input = encodeURIComponent(testData.input);
+ promise_test(t => {
+ let resolve;
+ const promise = new Promise(r => resolve = r);
+ const script = document.createElement("script");
+ t.add_cleanup(() => script.remove());
+ // A <script> element loading a classic script does not care about the MIME type, unless
+ // X-Content-Type-Options: nosniff is specified, in which case a JavaScript MIME type is
+ // enforced, which x/x is not.
+ if (testData.nosniff) {
+ script.onerror = resolve;
+ script.onload = t.unreached_func("Script should not have loaded");
+ } else {
+ script.onerror = t.unreached_func("Script should have loaded");
+ script.onload = resolve;
+ }
+ script.src = "resources/nosniff.py?nosniff=" + input;
+ document.body.appendChild(script);
+ return promise;
+ }, input);
+ }
+}
diff --git a/testing/web-platform/tests/fetch/nosniff/resources/css.py b/testing/web-platform/tests/fetch/nosniff/resources/css.py
new file mode 100644
index 0000000000..8afb56991d
--- /dev/null
+++ b/testing/web-platform/tests/fetch/nosniff/resources/css.py
@@ -0,0 +1,23 @@
+def main(request, response):
+ type = request.GET.first(b"type", None)
+ is_revalidation = request.headers.get(b"If-Modified-Since", None)
+
+ content = b"/* nothing to see here */"
+
+ response.add_required_headers = False
+ if is_revalidation is not None:
+ response.writer.write_status(304)
+ response.writer.write_header(b"x-content-type-options", b"nosniff")
+ response.writer.write_header(b"content-length", 0)
+ if(type != None):
+ response.writer.write_header(b"content-type", type)
+ response.writer.end_headers()
+ response.writer.write(b"")
+ else:
+ response.writer.write_status(200)
+ response.writer.write_header(b"x-content-type-options", b"nosniff")
+ response.writer.write_header(b"content-length", len(content))
+ if(type != None):
+ response.writer.write_header(b"content-type", type)
+ response.writer.end_headers()
+ response.writer.write(content)
diff --git a/testing/web-platform/tests/fetch/nosniff/resources/image.py b/testing/web-platform/tests/fetch/nosniff/resources/image.py
new file mode 100644
index 0000000000..9fd367c85c
--- /dev/null
+++ b/testing/web-platform/tests/fetch/nosniff/resources/image.py
@@ -0,0 +1,24 @@
+import os.path
+
+from wptserve.utils import isomorphic_decode
+
+def main(request, response):
+ type = request.GET.first(b"type", None)
+
+ if type != None and b"svg" in type:
+ filename = u"green-96x96.svg"
+ else:
+ filename = u"blue96x96.png"
+
+ path = os.path.join(os.path.dirname(isomorphic_decode(__file__)), u"../../../images", filename)
+ body = open(path, u"rb").read()
+
+ response.add_required_headers = False
+ response.writer.write_status(200)
+ response.writer.write_header(b"x-content-type-options", b"nosniff")
+ response.writer.write_header(b"content-length", len(body))
+ if(type != None):
+ response.writer.write_header(b"content-type", type)
+ response.writer.end_headers()
+
+ response.writer.write(body)
diff --git a/testing/web-platform/tests/fetch/nosniff/resources/js.py b/testing/web-platform/tests/fetch/nosniff/resources/js.py
new file mode 100644
index 0000000000..784050a2ca
--- /dev/null
+++ b/testing/web-platform/tests/fetch/nosniff/resources/js.py
@@ -0,0 +1,17 @@
+def main(request, response):
+ outcome = request.GET.first(b"outcome", b"f")
+ type = request.GET.first(b"type", b"Content-Type missing")
+
+ content = b"// nothing to see here"
+ content += b"\n"
+ content += b"log('FAIL: " + type + b"')" if (outcome == b"f") else b"p()"
+
+ response.add_required_headers = False
+ response.writer.write_status(200)
+ response.writer.write_header(b"x-content-type-options", b"nosniff")
+ response.writer.write_header(b"content-length", len(content))
+ if(type != b"Content-Type missing"):
+ response.writer.write_header(b"content-type", type)
+ response.writer.end_headers()
+
+ response.writer.write(content)
diff --git a/testing/web-platform/tests/fetch/nosniff/resources/nosniff.py b/testing/web-platform/tests/fetch/nosniff/resources/nosniff.py
new file mode 100644
index 0000000000..159ecfbebd
--- /dev/null
+++ b/testing/web-platform/tests/fetch/nosniff/resources/nosniff.py
@@ -0,0 +1,11 @@
+def main(request, response):
+ response.add_required_headers = False
+ output = b"HTTP/1.1 220 YOU HAVE NO POWER HERE\r\n"
+ output += b"Content-Length: 22\r\n"
+ output += b"Connection: close\r\n"
+ output += b"Content-Type: x/x\r\n"
+ output += request.GET.first(b"nosniff") + b"\r\n"
+ output += b"\r\n"
+ output += b"// nothing to see here"
+ response.writer.write(output)
+ response.close_connection = True
diff --git a/testing/web-platform/tests/fetch/nosniff/resources/worker.py b/testing/web-platform/tests/fetch/nosniff/resources/worker.py
new file mode 100644
index 0000000000..2d7e3f6c90
--- /dev/null
+++ b/testing/web-platform/tests/fetch/nosniff/resources/worker.py
@@ -0,0 +1,16 @@
+def main(request, response):
+ type = request.GET.first(b"type", None)
+
+ content = b"// nothing to see here"
+ content += b"\n"
+ content += b"this.postMessage('hi')"
+
+ response.add_required_headers = False
+ response.writer.write_status(200)
+ response.writer.write_header(b"x-content-type-options", b"nosniff")
+ response.writer.write_header(b"content-length", len(content))
+ if(type != None):
+ response.writer.write_header(b"content-type", type)
+ response.writer.end_headers()
+
+ response.writer.write(content)
diff --git a/testing/web-platform/tests/fetch/nosniff/resources/x-content-type-options.json b/testing/web-platform/tests/fetch/nosniff/resources/x-content-type-options.json
new file mode 100644
index 0000000000..080fc1990b
--- /dev/null
+++ b/testing/web-platform/tests/fetch/nosniff/resources/x-content-type-options.json
@@ -0,0 +1,62 @@
+[
+ {
+ "input": "X-Content-Type-Options: NOSNIFF",
+ "nosniff": true
+ },
+ {
+ "input": "x-content-type-OPTIONS: nosniff",
+ "nosniff": true
+ },
+ {
+ "input": "X-Content-Type-Options: nosniff,,@#$#%%&^&^*()()11!",
+ "nosniff": true
+ },
+ {
+ "input": "X-Content-Type-Options: @#$#%%&^&^*()()11!,nosniff",
+ "nosniff": false
+ },
+ {
+ "input": "X-Content-Type-Options: nosniff\r\nX-Content-Type-Options: no",
+ "nosniff": true
+ },
+ {
+ "input": "X-Content-Type-Options: no\r\nX-Content-Type-Options: nosniff",
+ "nosniff": false
+ },
+ {
+ "input": "X-Content-Type-Options:\r\nX-Content-Type-Options: nosniff",
+ "nosniff": false
+ },
+ {
+ "input": "X-Content-Type-Options: nosniff\r\nX-Content-Type-Options: nosniff",
+ "nosniff": true
+ },
+ {
+ "input": "X-Content-Type-Options: ,nosniff",
+ "nosniff": false
+ },
+ {
+ "input": "X-Content-Type-Options: nosniff\u000C",
+ "nosniff": false
+ },
+ {
+ "input": "X-Content-Type-Options: nosniff\u000B",
+ "nosniff": false
+ },
+ {
+ "input": "X-Content-Type-Options: nosniff\u000B,nosniff",
+ "nosniff": false
+ },
+ {
+ "input": "X-Content-Type-Options: 'NosniFF'",
+ "nosniff": false
+ },
+ {
+ "input": "X-Content-Type-Options: \"nosniFF\"",
+ "nosniff": false
+ },
+ {
+ "input": "Content-Type-Options: nosniff",
+ "nosniff": false
+ }
+]
diff --git a/testing/web-platform/tests/fetch/nosniff/script.html b/testing/web-platform/tests/fetch/nosniff/script.html
new file mode 100644
index 0000000000..e0b5dac709
--- /dev/null
+++ b/testing/web-platform/tests/fetch/nosniff/script.html
@@ -0,0 +1,43 @@
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+ var log = function() {}, // see comment below
+ p = function() {}, // see comment below
+ fails = [null, "", "x", "x/x", "text/html", "text/json"],
+ passes = ["text/javascript", "text/ecmascript", "text/ecmascript;blah", "text/javascript1.0"]
+
+ // Ideally we'd also check whether the scripts in fact execute, but that would involve
+ // timers and might get a bit racy without cross-browser support for the execute events.
+
+ const get_url = (mime, outcome) => {
+ let url = "resources/js.py"
+ if (mime != null) {
+ url += "?type=" + encodeURIComponent(mime)
+ }
+ if (outcome) {
+ url += "&outcome=p"
+ }
+ return url
+ }
+
+ fails.forEach(function(mime) {
+ async_test(function(t) {
+ var script = document.createElement("script")
+ script.onerror = t.step_func_done(function(){})
+ script.onload = t.unreached_func("Unexpected load event")
+ script.src = get_url(mime)
+ document.body.appendChild(script)
+ }, "URL query: " + mime)
+ })
+
+ passes.forEach(function(mime) {
+ async_test(function(t) {
+ var script = document.createElement("script")
+ script.onerror = t.unreached_func("Unexpected error event")
+ script.onload = t.step_func_done(function(){})
+ script.src = get_url(mime, true)
+ document.body.appendChild(script)
+ }, "URL query: " + mime)
+ })
+</script>
diff --git a/testing/web-platform/tests/fetch/nosniff/stylesheet.html b/testing/web-platform/tests/fetch/nosniff/stylesheet.html
new file mode 100644
index 0000000000..8f2b5476e9
--- /dev/null
+++ b/testing/web-platform/tests/fetch/nosniff/stylesheet.html
@@ -0,0 +1,60 @@
+<!-- quirks mode is important, text/css is already required otherwise -->
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+ var fails = [null, "", "x", "x/x", "text/html", "text/json"],
+ passes = ["text/css", "text/css;charset=utf-8", "text/css;blah"]
+
+ const get_url = (mime) => {
+ let url = "resources/css.py"
+ if (mime != null) {
+ url += "?type=" + encodeURIComponent(mime)
+ }
+ return url
+ }
+
+ fails.forEach(function(mime) {
+ async_test(function(t) {
+ var link = document.createElement("link")
+ link.rel = "stylesheet"
+ link.onerror = t.step_func_done()
+ link.onload = t.unreached_func("Unexpected load event")
+ link.href = get_url(mime)
+ document.body.appendChild(link)
+ }, "URL query: " + mime)
+ })
+
+ fails.forEach(function(mime) {
+ async_test(function(t) {
+ var link = document.createElement("link")
+ link.rel = "stylesheet"
+ link.onerror = t.step_func_done()
+ link.onload = t.unreached_func("Unexpected load event")
+ link.href = get_url(mime)
+ document.body.appendChild(link)
+ }, "Revalidated URL query: " + mime)
+ })
+
+ passes.forEach(function(mime) {
+ async_test(function(t) {
+ var link = document.createElement("link")
+ link.rel = "stylesheet"
+ link.onerror = t.unreached_func("Unexpected error event")
+ link.onload = t.step_func_done()
+ link.href = get_url(mime)
+ document.body.appendChild(link)
+ }, "URL query: " + mime)
+ })
+
+ passes.forEach(function(mime) {
+ async_test(function(t) {
+ var link = document.createElement("link")
+ link.rel = "stylesheet"
+ link.onerror = t.unreached_func("Unexpected error event")
+ link.onload = t.step_func_done()
+ link.href = get_url(mime)
+ document.body.appendChild(link)
+ }, "Revalidated URL query: " + mime)
+ })
+</script>
diff --git a/testing/web-platform/tests/fetch/nosniff/worker.html b/testing/web-platform/tests/fetch/nosniff/worker.html
new file mode 100644
index 0000000000..c8c1076df5
--- /dev/null
+++ b/testing/web-platform/tests/fetch/nosniff/worker.html
@@ -0,0 +1,28 @@
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+ var workers = [],
+ fails = ["", "?type=", "?type=x", "?type=x/x", "?type=text/html", "?type=text/json"],
+ passes = ["?type=text/javascript", "?type=text/ecmascript", "?type=text/ecmascript;yay"]
+
+ fails.forEach(function(urlpart) {
+ async_test(function(t) {
+ var w = new Worker("resources/worker.py" + urlpart)
+ w.onmessage = t.unreached_func("Unexpected message event")
+ w.onerror = t.step_func_done(function(){})
+ workers.push(w) // avoid GC
+ }, "URL query: " + urlpart)
+ })
+
+ passes.forEach(function(urlpart) {
+ async_test(function(t) {
+ var w = new Worker("resources/worker.py" + urlpart)
+ w.onmessage = t.step_func_done(function(e){
+ assert_equals(e.data, "hi")
+ })
+ w.onerror = t.unreached_func("Unexpected error event")
+ workers.push(w) // avoid GC
+ }, "URL query: " + urlpart)
+ })
+</script>