diff options
Diffstat (limited to 'testing/web-platform/tests/content-security-policy/inside-worker')
18 files changed, 749 insertions, 0 deletions
diff --git a/testing/web-platform/tests/content-security-policy/inside-worker/dedicatedworker-connect-src.html b/testing/web-platform/tests/content-security-policy/inside-worker/dedicatedworker-connect-src.html new file mode 100644 index 0000000000..a1117d2e73 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/inside-worker/dedicatedworker-connect-src.html @@ -0,0 +1,57 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<!-- Test the 'connect-src' directive on dedicated workers --> +<script> + let reportCookieName = location.pathname.split('/')[ + location.pathname.split('/').length - 1].split('.')[0]; + let reportID = document.cookie.split('; ') + .find(cookie => cookie.startsWith(reportCookieName + '=')) + .split('=')[1].trim(); + + promise_test(async t => { + // Dedicated workers do not inherit CSP. + await fetch_tests_from_worker( + new Worker("./support/connect-src-allow.sub.js")); + + // Dedicated workers honor CSP received in their response headers. + await fetch_tests_from_worker( + new Worker( + `./support/connect-src-self.sub.js?id=${reportID}` + + `&test-name=connect-src 'self'` + + `&pipe=sub|header(Content-Security-Policy,` + + `connect-src 'self' ; report-uri ` + + `/reporting/resources/report.py?op=put%26reportID=${reportID})`)); + + + let blob = await fetch(`./support/connect-src-self.sub.js?id=${reportID}` + + `&test-name=connect-src 'self'`) + .then(r => r.blob()); + + // 'blob:' URL workers inherit CSP. + let blob_url = URL.createObjectURL(blob); + await fetch_tests_from_worker(new Worker(blob_url)); + + if (window.webkitRequestFileSystem) { + // 'filesystem:' URL workers inherit CSP. + let fs = await new Promise(resolve => + window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, resolve)); + + let fs_entry = await new Promise(resolve => + fs.root.getFile('dedicated-connect-src.js', + { create: true }, resolve)); + + let writer = await new Promise(resolve => fs_entry.createWriter(resolve)); + + writer.onerror = t.unreached_func("Could not write to filesystem entry"); + + writer.write(blob); + await new Promise(resolve => writer.onwriteend = resolve); + + let fs_url = fs_entry.toURL(); + await fetch_tests_from_worker(new Worker(fs_url)); + + await new Promise(resolve => fs_entry.remove(resolve)); + } + }); +</script> diff --git a/testing/web-platform/tests/content-security-policy/inside-worker/dedicatedworker-connect-src.html.sub.headers b/testing/web-platform/tests/content-security-policy/inside-worker/dedicatedworker-connect-src.html.sub.headers new file mode 100644 index 0000000000..6a1d758ce7 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/inside-worker/dedicatedworker-connect-src.html.sub.headers @@ -0,0 +1,6 @@ +Expires: Mon, 26 Jul 1997 05:00:00 GMT +Cache-Control: no-store, no-cache, must-revalidate +Cache-Control: post-check=0, pre-check=0, false +Pragma: no-cache +Set-Cookie: dedicatedworker-connect-src={{$id:uuid()}}; Path=/content-security-policy/inside-worker/ +Content-Security-Policy: connect-src 'self' ; report-uri /reporting/resources/report.py?op=put&reportID={{$id}} diff --git a/testing/web-platform/tests/content-security-policy/inside-worker/dedicatedworker-report-only.html b/testing/web-platform/tests/content-security-policy/inside-worker/dedicatedworker-report-only.html new file mode 100644 index 0000000000..270e705415 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/inside-worker/dedicatedworker-report-only.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<!-- Test the 'connect-src' directive on dedicated workers in report-only mode +--> +<script> + let reportCookieName = location.pathname.split('/')[ + location.pathname.split('/').length - 1].split('.')[0]; + let reportID = document.cookie.split('; ') + .find(cookie => cookie.startsWith(reportCookieName + '=')) + .split('=')[1].trim(); + + fetch_tests_from_worker(new Worker( + `./support/connect-src-self-report-only.sub.js?id=${reportID}`)); +</script> diff --git a/testing/web-platform/tests/content-security-policy/inside-worker/dedicatedworker-report-only.html.sub.headers b/testing/web-platform/tests/content-security-policy/inside-worker/dedicatedworker-report-only.html.sub.headers new file mode 100644 index 0000000000..f82fd74759 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/inside-worker/dedicatedworker-report-only.html.sub.headers @@ -0,0 +1,6 @@ +Expires: Mon, 26 Jul 1997 05:00:00 GMT +Cache-Control: no-store, no-cache, must-revalidate +Cache-Control: post-check=0, pre-check=0, false +Pragma: no-cache +Set-Cookie: dedicatedworker-report-only={{$id:uuid()}}; Path=/content-security-policy/inside-worker/ +Content-Security-Policy-Report-Only: connect-src 'self'; report-uri /reporting/resources/report.py?op=put&reportID={{$id}} diff --git a/testing/web-platform/tests/content-security-policy/inside-worker/dedicatedworker-script-src.html b/testing/web-platform/tests/content-security-policy/inside-worker/dedicatedworker-script-src.html new file mode 100644 index 0000000000..296ba58f5e --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/inside-worker/dedicatedworker-script-src.html @@ -0,0 +1,57 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<!-- Test the 'script-src' directive on dedicated workers --> +<script nonce="a"> + let reportCookieName = location.pathname.split('/')[ + location.pathname.split('/').length - 1].split('.')[0]; + let reportID = document.cookie.split('; ') + .find(cookie => cookie.startsWith(reportCookieName + '=')) + .split('=')[1].trim(); + + promise_test(async t => { + // Dedicated workers do not inherit CSP in general. + await fetch_tests_from_worker( + new Worker("./support/script-src-allow.sub.js")); + + // Dedicated workers honor CSP received in their response headers. + await fetch_tests_from_worker( + new Worker( + `./support/script-src-self.sub.js?id=${reportID}` + + `&test-name=script-src 'self'` + + `&pipe=sub|header(Content-Security-Policy,` + + `script-src 'self' ; report-uri ` + + `/reporting/resources/report.py?op=put%26reportID=${reportID})`)); + + + let blob = await fetch(`./support/script-src-self.sub.js?id=${reportID}` + + `&test-name=script-src 'self'`) + .then(r => r.blob()); + + // 'blob:' URL workers inherit CSP. + let blob_url = URL.createObjectURL(blob); + await fetch_tests_from_worker(new Worker(blob_url)); + + if (window.webkitRequestFileSystem) { + // 'filesystem:' URL workers inherit CSP. + let fs = await new Promise(resolve => + window.webkitRequestFileSystem(window.TEMPORARY, 1024*1024, resolve)); + + let fs_entry = await new Promise(resolve => + fs.root.getFile('dedicated-script-src.js', + { create: true }, resolve)); + + let writer = await new Promise(resolve => fs_entry.createWriter(resolve)); + + writer.onerror = t.unreached_func("Could not write to filesystem entry"); + + writer.write(blob); + await new Promise(resolve => writer.onwriteend = resolve); + + let fs_url = fs_entry.toURL(); + await fetch_tests_from_worker(new Worker(fs_url)); + + await new Promise(resolve => fs_entry.remove(resolve)); + } + }); +</script> diff --git a/testing/web-platform/tests/content-security-policy/inside-worker/dedicatedworker-script-src.html.sub.headers b/testing/web-platform/tests/content-security-policy/inside-worker/dedicatedworker-script-src.html.sub.headers new file mode 100644 index 0000000000..c7768a5af0 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/inside-worker/dedicatedworker-script-src.html.sub.headers @@ -0,0 +1,6 @@ +Expires: Mon, 26 Jul 1997 05:00:00 GMT +Cache-Control: no-store, no-cache, must-revalidate +Cache-Control: post-check=0, pre-check=0, false +Pragma: no-cache +Set-Cookie: dedicatedworker-script-src={{$id:uuid()}}; Path=/content-security-policy/inside-worker/ +Content-Security-Policy: script-src 'self' 'nonce-a' blob: filesystem: ; report-uri /reporting/resources/report.py?op=put&reportID={{$id}} diff --git a/testing/web-platform/tests/content-security-policy/inside-worker/serviceworker-connect-src.https.sub.html b/testing/web-platform/tests/content-security-policy/inside-worker/serviceworker-connect-src.https.sub.html new file mode 100644 index 0000000000..f455fe6a16 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/inside-worker/serviceworker-connect-src.https.sub.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<!-- Test the 'connect-src' directive on service workers --> +<meta http-equiv="content-security-policy" content="connect-src 'self'"> +<script> + [ // Service workers do not inherit CSP. + "./support/connect-src-allow.sub.js", + + // Service workers honor CSP received in their response headers. + "./support/connect-src-self.sub.js?id={{$id1:uuid()}}" + + "&test-name=connect-src 'self'" + + "&pipe=sub|header(Content-Security-Policy," + + "connect-src 'self' ; report-uri " + + "/reporting/resources/report.py?op=put%26reportID={{$id1}})", + + // Also test that connect-src falls back to default-src. + "./support/connect-src-self.sub.js?id={{$id2:uuid()}}" + + "&test-name=default-src 'self'" + + "&pipe=sub|header(Content-Security-Policy," + + "default-src 'self' ; report-uri " + + "/reporting/resources/report.py?op=put%26reportID={{$id2}})"] + .forEach(url => { + promise_test(async t => { + let r = await navigator.serviceWorker.register( + url, {scope: "./support/blank.html"}); + t.add_cleanup(_ => r.unregister()); + let sw = r.active || r.installing || r.waiting; + await fetch_tests_from_worker(sw); + }); + }); +</script> diff --git a/testing/web-platform/tests/content-security-policy/inside-worker/serviceworker-report-only.https.sub.html b/testing/web-platform/tests/content-security-policy/inside-worker/serviceworker-report-only.https.sub.html new file mode 100644 index 0000000000..b2bf3e566f --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/inside-worker/serviceworker-report-only.https.sub.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<!-- Test the 'connect-src' directive on service workers in report-only mode +--> +<script> + promise_test(async t => { + let r = await navigator.serviceWorker.register( + "./support/connect-src-self-report-only.sub.js?id={{uuid()}}", + {scope: "./support/blank.html"}); + t.add_cleanup(_ => r.unregister()); + let sw = r.active || r.installing || r.waiting; + await fetch_tests_from_worker(sw); + }); +</script> diff --git a/testing/web-platform/tests/content-security-policy/inside-worker/serviceworker-script-src.https.sub.html b/testing/web-platform/tests/content-security-policy/inside-worker/serviceworker-script-src.https.sub.html new file mode 100644 index 0000000000..5631786cc5 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/inside-worker/serviceworker-script-src.https.sub.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<!-- Test the 'script-src' directive on service workers --> +<meta http-equiv="content-security-policy" content="script-src 'self' 'nonce-a' blob: filesystem:"> +<script nonce="a"> + [ // Service worker do not inherit CSP. + "./support/script-src-allow.sub.js", + + // Service workers honor CSP received in their response headers. + "./support/script-src-self.sub.js?id={{$id1:uuid()}}" + + "&test-name=script-src 'self'" + + "&pipe=sub|header(Content-Security-Policy," + + "script-src 'self' ; report-uri " + + "/reporting/resources/report.py?op=put%26reportID={{$id1}})", + + // Also check that script-src falls back to default-src. + "./support/script-src-self.sub.js?id={{$id2:uuid()}}" + + "&test-name=default-src 'self'" + + "&pipe=sub|header(Content-Security-Policy," + + "default-src 'self' ; report-uri " + + "/reporting/resources/report.py?op=put%26reportID={{$id2}})"] + .forEach(url => { + promise_test(async t => { + let r = await navigator.serviceWorker.register( + url, {scope: "./support/blank.html"}); + t.add_cleanup(_ => r.unregister()); + let sw = r.active || r.installing || r.waiting; + await fetch_tests_from_worker(sw); + }); + }); +</script> diff --git a/testing/web-platform/tests/content-security-policy/inside-worker/sharedworker-connect-src.sub.html b/testing/web-platform/tests/content-security-policy/inside-worker/sharedworker-connect-src.sub.html new file mode 100644 index 0000000000..24717bc9c6 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/inside-worker/sharedworker-connect-src.sub.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<!-- Test the 'connect-src' directive on shared workers --> +<meta http-equiv="content-security-policy" content="connect-src 'self'"> +<script> + promise_test(async () => { + // Shared workers do not inherit CSP. + await fetch_tests_from_worker( + new SharedWorker("./support/connect-src-allow.sub.js")); + + // Shared workers honor CSP received in their response headers. + await fetch_tests_from_worker( + new SharedWorker( + "./support/connect-src-self.sub.js?id={{$id1:uuid()}}" + + "&test-name=connect-src 'self'" + + "&pipe=sub|header(Content-Security-Policy," + + "connect-src 'self' ; report-uri " + + "/reporting/resources/report.py?op=put%26reportID={{$id1}})")); + + // Also test that connect-src falls back to default-src. + await fetch_tests_from_worker( + new SharedWorker( + "./support/connect-src-self.sub.js?id={{$id2:uuid()}}" + + "&test-name=default-src 'self'" + + "&pipe=sub|header(Content-Security-Policy," + + "default-src 'self' ; report-uri " + + "/reporting/resources/report.py?op=put%26reportID={{$id2}})")); + }); +</script> diff --git a/testing/web-platform/tests/content-security-policy/inside-worker/sharedworker-report-only.sub.html b/testing/web-platform/tests/content-security-policy/inside-worker/sharedworker-report-only.sub.html new file mode 100644 index 0000000000..8233f00075 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/inside-worker/sharedworker-report-only.sub.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<!-- Test the 'connect-src' directive on shared workers in report-only mode --> +<script> + fetch_tests_from_worker(new SharedWorker( + "./support/connect-src-self-report-only.sub.js?id={{uuid()}}")); +</script> diff --git a/testing/web-platform/tests/content-security-policy/inside-worker/sharedworker-script-src.sub.html b/testing/web-platform/tests/content-security-policy/inside-worker/sharedworker-script-src.sub.html new file mode 100644 index 0000000000..88f56bdba7 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/inside-worker/sharedworker-script-src.sub.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<!-- Test the 'script-src' directive on shared workers --> +<meta http-equiv="content-security-policy" content="script-src 'self' 'nonce-a' blob: filesystem:"> +<script nonce="a"> + promise_test(async () => { + // Shared workers do not inherit CSP. + await fetch_tests_from_worker( + new SharedWorker("./support/script-src-allow.sub.js")); + + // Service workers honor CSP received in their response headers. + await fetch_tests_from_worker( + new SharedWorker( + "./support/script-src-self.sub.js?id={{$id1:uuid()}}" + + "&test-name=script-src 'self'" + + "&pipe=sub|header(Content-Security-Policy," + + "script-src 'self' ; report-uri " + + "/reporting/resources/report.py?op=put%26reportID={{$id1}})")); + + // Also check that script-src falls back to default-src. + await fetch_tests_from_worker( + new SharedWorker( + "./support/script-src-self.sub.js?id={{$id2:uuid()}}" + + "&test-name=default-src 'self'" + + "&pipe=sub|header(Content-Security-Policy," + + "default-src 'self' ; report-uri " + + "/reporting/resources/report.py?op=put%26reportID={{$id2}})")); + }); +</script> diff --git a/testing/web-platform/tests/content-security-policy/inside-worker/support/connect-src-allow.sub.js b/testing/web-platform/tests/content-security-policy/inside-worker/support/connect-src-allow.sub.js new file mode 100644 index 0000000000..7f0ee1f837 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/inside-worker/support/connect-src-allow.sub.js @@ -0,0 +1,82 @@ +importScripts("{{location[server]}}/resources/testharness.js"); +importScripts("{{location[server]}}/content-security-policy/support/testharness-helper.js"); + +let base_same_origin_url = + "{{location[server]}}/content-security-policy/support/resource.py"; +let base_cross_origin_url = + "https://{{hosts[][www]}}:{{ports[https][1]}}" + + "/content-security-policy/support/resource.py"; + +// Same-origin +promise_test(t => { + let url = `${base_same_origin_url}?same-origin-fetch`; + assert_no_csp_event_for_url(t, url); + + return fetch(url) + .then(t.step_func(r => assert_equals(r.status, 200))); +}, "Same-origin 'fetch()' in " + self.location.protocol + " without CSP"); + +// XHR is not available in service workers. +if (self.XMLHttpRequest) { + promise_test(t => { + let url = `${base_same_origin_url}?same-origin-xhr`; + assert_no_csp_event_for_url(t, url); + + return new Promise((resolve, reject) => { + let xhr = new XMLHttpRequest(); + xhr.open("GET", url); + xhr.onload = resolve; + xhr.onerror = _ => reject("xhr.open should success."); + xhr.send(); + }); + }, "Same-origin XHR in " + self.location.protocol + " without CSP"); +} + +// Cross-origin +promise_test(t => { + let url = `${base_cross_origin_url}?cross-origin-fetch`; + assert_no_csp_event_for_url(t, url); + + return fetch(url) + .then(t.step_func(r => assert_equals(r.status, 200))); +}, "Cross-origin 'fetch()' in " + self.location.protocol + " without CSP"); + +// XHR is not available in service workers. +if (self.XMLHttpRequest) { + promise_test(t => { + let url = `${base_cross_origin_url}?cross-origin-xhr`; + assert_no_csp_event_for_url(t, url); + + return new Promise((resolve, reject) => { + let xhr = new XMLHttpRequest(); + xhr.open("GET", url); + xhr.onload = resolve; + xhr.onerror = _ => reject("xhr.open should success."); + xhr.send(); + }); + }, "Cross-origin XHR in " + self.location.protocol + " without CSP"); +} + +// Same-origin redirecting to cross-origin +promise_test(t => { + let url = `{{location[server]}}/common/redirect-opt-in.py?` + + `status=307&location=${base_cross_origin_url}?cross-origin-fetch`; + assert_no_csp_event_for_url(t, url); + + return fetch(url) + .then(t.step_func(r => assert_equals(r.status, 200))); +}, "Same-origin => cross-origin 'fetch()' in " + self.location.protocol + + " without CSP"); + +// WebSocket +promise_test(async function(t) { + let url = "wss://{{host}}:{{ports[wss][0]}}/echo"; + assert_no_csp_event_for_url(t, url); + + return new Promise(resolve => { + let ws = new WebSocket(url); + ws.onopen = resolve; + }); +}, "WebSocket without CSP"); + +done(); diff --git a/testing/web-platform/tests/content-security-policy/inside-worker/support/connect-src-self-report-only.sub.js b/testing/web-platform/tests/content-security-policy/inside-worker/support/connect-src-self-report-only.sub.js new file mode 100644 index 0000000000..c624671476 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/inside-worker/support/connect-src-self-report-only.sub.js @@ -0,0 +1,130 @@ +importScripts("{{location[server]}}/resources/testharness.js"); +importScripts("{{location[server]}}/content-security-policy/support/testharness-helper.js"); + +let base_same_origin_url = + "{{location[server]}}/content-security-policy/support/resource.py"; + +// Same-origin +promise_test(t => { + let url = `${base_same_origin_url}?same-origin-fetch`; + assert_no_csp_event_for_url(t, url); + + return fetch(url) + .then(t.step_func(r => assert_equals(r.status, 200))); +}, "Same-origin 'fetch()'."); + +// XHR is not available in service workers. +if (self.XMLHttpRequest) { + promise_test(t => { + let url = `${base_same_origin_url}?same-origin-xhr`; + assert_no_csp_event_for_url(t, url); + + return new Promise((resolve, reject) => { + var xhr = new XMLHttpRequest(); + xhr.open("GET", url); + xhr.onload = resolve; + xhr.onerror = _ => reject("xhr.open should success."); + xhr.send(); + }); + }, "Same-origin XHR."); +} + +let base_cross_origin_url = + "https://{{hosts[][www]}}:{{ports[https][1]}}" + + "/content-security-policy/support/resource.py"; +let fetch_cross_origin_url = `${base_cross_origin_url}?cross-origin-fetch`; + +// Cross-origin +promise_test(t => { + let url = fetch_cross_origin_url; + + return Promise.all([ + waitUntilCSPEventForURL(t, url), + fetch(url) + ]); +}, "Cross-origin 'fetch()'."); + +let xhr_cross_origin_url = `${base_cross_origin_url}?cross-origin-xhr`; + +// XHR is not available in service workers. +if (self.XMLHttpRequest) { + promise_test(t => { + let url = xhr_cross_origin_url; + + return Promise.all([ + waitUntilCSPEventForURL(t, url), + new Promise((resolve, reject) => { + var xhr = new XMLHttpRequest(); + xhr.open("GET", url); + xhr.onload = resolve; + xhr.onerror = _ => reject("xhr.open should not have thrown."); + xhr.send(); + }) + ]); + }, "Cross-origin XHR."); +} + +let redirect_url = `{{location[server]}}/common/redirect-opt-in.py?` + + `status=307&location=${fetch_cross_origin_url}`; + +// Same-origin redirecting to cross-origin +promise_test(t => { + let url = redirect_url; + + return Promise.all([ + waitUntilCSPEventForURL(t, url), + fetch(url) + ]); +}, "Same-origin => cross-origin 'fetch()'."); + +let websocket_url = "wss://{{host}}:{{ports[wss][0]}}/echo"; + +// The WebSocket URL is not the same as 'self' +promise_test(t => { + return Promise.all([ + waitUntilCSPEventForURL(t, websocket_url), + new Promise(resolve => { + let ws = new WebSocket(websocket_url); + ws.onopen = resolve; + }) + ]); +}, "WebSocket."); + +let expected_blocked_urls = self.XMLHttpRequest + ? [ fetch_cross_origin_url, xhr_cross_origin_url, redirect_url, websocket_url ] + : [ fetch_cross_origin_url, redirect_url, websocket_url ]; + +promise_test(async t => { + let report_url = `{{location[server]}}/reporting/resources/report.py?` + + `?op=retrieve_report&reportID={{GET[id]}}` + + `&min_count=${expected_blocked_urls.length}`; + + let response = await fetch(report_url); + assert_equals(response.status, 200, "Fetching reports failed"); + + let response_json = await response.json(); + let reports = response_json.map(x => x["csp-report"]); + + assert_array_equals( + reports.map(x => x["blocked-uri"]).sort(), + expected_blocked_urls.sort(), + "Reports do not match"); + reports.forEach(x => { + assert_equals( + x["violated-directive"], "connect-src", + "Violated directive in report does not match"); + assert_equals( + x["effective-directive"], "connect-src", + "Effective directive in report does not match"); + assert_equals( + x["disposition"], "report", + "Disposition in report does not match"); + assert_equals( + x["document-uri"], + "{{location[server]}}/content-security-policy/inside-worker/" + + "support/connect-src-self-report-only.sub.js?id={{GET[id]}}", + "Document uri in report does not match"); + }); +}); + +done(); diff --git a/testing/web-platform/tests/content-security-policy/inside-worker/support/connect-src-self-report-only.sub.js.sub.headers b/testing/web-platform/tests/content-security-policy/inside-worker/support/connect-src-self-report-only.sub.js.sub.headers new file mode 100644 index 0000000000..02e8e1f433 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/inside-worker/support/connect-src-self-report-only.sub.js.sub.headers @@ -0,0 +1,5 @@ +Expires: Mon, 26 Jul 1997 05:00:00 GMT +Cache-Control: no-store, no-cache, must-revalidate +Cache-Control: post-check=0, pre-check=0, false +Pragma: no-cache +Content-Security-Policy-Report-Only: connect-src 'self'; report-uri /reporting/resources/report.py?op=put&reportID={{GET[id]}} diff --git a/testing/web-platform/tests/content-security-policy/inside-worker/support/connect-src-self.sub.js b/testing/web-platform/tests/content-security-policy/inside-worker/support/connect-src-self.sub.js new file mode 100644 index 0000000000..3c3ecc01c2 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/inside-worker/support/connect-src-self.sub.js @@ -0,0 +1,143 @@ +importScripts("{{location[server]}}/resources/testharness.js"); +importScripts("{{location[server]}}/content-security-policy/support/testharness-helper.js"); + +let base_same_origin_url = + "{{location[server]}}/content-security-policy/support/resource.py"; +let base_cross_origin_url = + "https://{{hosts[][www]}}:{{ports[https][1]}}" + + "/content-security-policy/support/resource.py"; + +// Same-origin +promise_test(t => { + let url = `${base_same_origin_url}?same-origin-fetch`; + assert_no_csp_event_for_url(t, url); + + return fetch(url) + .then(t.step_func(r => assert_equals(r.status, 200))); +}, "Same-origin 'fetch()' in " + self.location.protocol + + " with {{GET[test-name]}}"); + +// XHR is not available in service workers. +if (self.XMLHttpRequest) { + promise_test(t => { + let url = `${base_same_origin_url}?same-origin-xhr`; + assert_no_csp_event_for_url(t, url); + + return new Promise((resolve, reject) => { + let xhr = new XMLHttpRequest(); + xhr.open("GET", url); + xhr.onload = resolve; + xhr.onerror = _ => reject("xhr.open should success."); + xhr.send(); + }); + }, "Same-origin XHR in " + self.location.protocol + + " with {{GET[test-name]}}"); +} + +let fetch_cross_origin_url = `${base_cross_origin_url}?cross-origin-fetch`; + +// Cross-origin +promise_test(t => { + let url = fetch_cross_origin_url; + + return Promise.all([ + waitUntilCSPEventForURL(t, url), + fetch(url) + .then(t.step_func(_ => assert_unreached( + "cross-origin fetch should have thrown."))) + .catch(t.step_func(e => assert_true(e instanceof TypeError))) + ]); +}, "Cross-origin 'fetch()' in " + self.location.protocol + + " with {{GET[test-name]}}"); + +let xhr_cross_origin_url = `${base_cross_origin_url}?cross-origin-xhr`; + +// XHR is not available in service workers. +if (self.XMLHttpRequest) { + promise_test(t => { + let url = xhr_cross_origin_url; + + return Promise.all([ + waitUntilCSPEventForURL(t, url), + new Promise((resolve, reject) => { + let xhr = new XMLHttpRequest(); + xhr.open("GET", url); + xhr.onload = _ => reject("xhr.open should have thrown."); + xhr.onerror = resolve; + xhr.send(); + }) + ]); + }, "Cross-origin XHR in " + self.location.protocol + + " with {{GET[test-name]}}"); +} + +let redirect_url = `{{location[server]}}/common/redirect-opt-in.py?` + + `status=307&location=${fetch_cross_origin_url}`; + +// Same-origin redirecting to cross-origin +promise_test(t => { + let url = redirect_url; + + return Promise.all([ + waitUntilCSPEventForURL(t, url), + fetch(url) + .then(t.step_func(_ => assert_unreached( + "cross-origin redirect should have thrown."))) + .catch(t.step_func(e => assert_true(e instanceof TypeError))) + ]); +}, "Same-origin => cross-origin 'fetch()' in " + self.location.protocol + + " with {{GET[test-name]}}"); + + +let websocket_url = "wss://{{host}}:{{ports[wss][0]}}/echo"; + +// The WebSocket URL is not the same as 'self' +promise_test(t => { + return Promise.all([ + waitUntilCSPEventForURL(t, websocket_url), + new Promise((resolve, reject) => { + // Firefox throws in the constructor, Chrome triggers the error event. + try { + let ws = new WebSocket(websocket_url); + ws.onerror = resolve; + ws.onopen = reject; // unexpected + } catch (e) { + resolve(); + } + }) + ]); +}, "WebSocket in " + self.location.protocol + " with {{GET[test-name]}}"); + +let expected_blocked_urls = self.XMLHttpRequest + ? [ fetch_cross_origin_url, xhr_cross_origin_url, redirect_url, websocket_url ] + : [ fetch_cross_origin_url, redirect_url, websocket_url ]; + +promise_test(async t => { + let report_url = `{{location[server]}}/reporting/resources/report.py` + + `?op=retrieve_report&reportID={{GET[id]}}` + + `&min_count=${expected_blocked_urls.length}`; + + let response = await fetch(report_url); + assert_equals(response.status, 200, "Fetching reports failed"); + + let response_json = await response.json(); + let reports = response_json.map(x => x["csp-report"]); + + assert_array_equals( + reports.map(x => x["blocked-uri"]).sort(), + expected_blocked_urls.sort(), + "Reports do not match"); + reports.forEach(x => { + assert_equals( + x["violated-directive"], "connect-src", + "Violated directive in report does not match"); + assert_equals( + x["effective-directive"], "connect-src", + "Effective directive in report does not match"); + assert_equals( + x["disposition"], "enforce", + "Effective directive in report does not match"); + }); +}, "Reports match in " + self.location.protocol + " with {{GET[test-name]}}"); + +done(); diff --git a/testing/web-platform/tests/content-security-policy/inside-worker/support/script-src-allow.sub.js b/testing/web-platform/tests/content-security-policy/inside-worker/support/script-src-allow.sub.js new file mode 100644 index 0000000000..7c66953154 --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/inside-worker/support/script-src-allow.sub.js @@ -0,0 +1,24 @@ +importScripts("{{location[server]}}/resources/testharness.js"); + +test(t => { + importScripts("https://{{hosts[][www]}}:{{ports[https][1]}}" + + "/content-security-policy/support/testharness-helper.js"); +}, "Cross-origin `importScripts()` not blocked in " + self.location.protocol + + " withour CSP"); + +test(t => { + assert_equals(2, eval("1+1")); + assert_equals(2, (new Function("return 1+1;"))()); +}, "`eval()` not blocked in " + self.location.protocol + + " without CSP"); + +async_test(t => { + self.callback = t.step_func_done(); + + setTimeout("self.callback();", 1); + setTimeout(t.step_func(_ => + assert_unreached("callback not called.")), 2); +}, "`setTimeout([string])` not blocked in " + self.location.protocol + + " without CSP"); + +done(); diff --git a/testing/web-platform/tests/content-security-policy/inside-worker/support/script-src-self.sub.js b/testing/web-platform/tests/content-security-policy/inside-worker/support/script-src-self.sub.js new file mode 100644 index 0000000000..aac5b4326d --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/inside-worker/support/script-src-self.sub.js @@ -0,0 +1,71 @@ +importScripts("{{location[server]}}/resources/testharness.js"); +importScripts("{{location[server]}}/content-security-policy/support/testharness-helper.js"); + +let importscripts_url ="https://{{hosts[][www]}}:{{ports[https][1]}}" + + "/content-security-policy/support/var-a.js"; + +promise_test(async t => { + self.a = false; + assert_throws_dom("NetworkError", + _ => importScripts(importscripts_url), + "importScripts should throw `NetworkError`"); + assert_false(self.a); + return waitUntilCSPEventForURL(t, importscripts_url); +}, "Cross-origin `importScripts()` blocked in " + self.location.protocol + + " with {{GET[test-name]}}"); + +promise_test(t => { + assert_throws_js(EvalError, + _ => eval("1 + 1"), + "`eval()` should throw 'EvalError'."); + + assert_throws_js(EvalError, + _ => new Function("1 + 1"), + "`new Function()` should throw 'EvalError'."); + return Promise.all([ + waitUntilCSPEventForEval(t, 19), + waitUntilCSPEventForEval(t, 23), + ]); +}, "`eval()` blocked in " + self.location.protocol + + " with {{GET[test-name]}}"); + +promise_test(t => { + self.setTimeoutTest = t; + let result = setTimeout("(self.setTimeoutTest.unreached_func(" + + "'setTimeout([string]) should not execute.'))()", 1); + assert_equals(result, 0); + return waitUntilCSPEventForEval(t, 34); +}, "`setTimeout([string])` blocked in " + self.location.protocol + + " with {{GET[test-name]}}"); + +promise_test(async t => { + let report_url = "{{location[server]}}/reporting/resources/report.py" + + "?op=retrieve_report&reportID={{GET[id]}}&min_count=4"; + + let response = await fetch(report_url); + assert_equals(response.status, 200, "Fetching reports failed"); + + let response_json = await response.json(); + let reports = response_json.map(x => x["csp-report"]); + + assert_array_equals( + reports.map(x => x["blocked-uri"]).sort(), + [ importscripts_url, "eval", "eval", "eval" ].sort(), + "Reports do not match"); + assert_array_equals( + reports.map(x => x["violated-directive"]).sort(), + [ "script-src-elem", "script-src", "script-src", "script-src" ].sort(), + "Violated directive in report does not match"); + assert_array_equals( + reports.map(x => x["effective-directive"]).sort(), + [ "script-src-elem", "script-src", "script-src", "script-src" ].sort(), + "Effective directive in report does not match"); + reports.forEach(x => { + assert_equals( + x["disposition"], "enforce", + "Disposition in report does not match"); + }); +}, "Reports are sent for " + self.location.protocol + + " with {{GET[test-name]}}"); + +done(); |