diff --git a/content-security-policy/report-hash/default-src.https.window.js b/content-security-policy/report-hash/default-src.https.window.js new file mode 100644 index 00000000000000..c8edc03fd3fe61 --- /dev/null +++ b/content-security-policy/report-hash/default-src.https.window.js @@ -0,0 +1,3 @@ +// META: script=/reporting/resources/report-helper.js +// META: script=resources/report-hash-test-runner.sub.js +run_tests(); diff --git a/content-security-policy/report-hash/default-src.https.window.js.sub.headers b/content-security-policy/report-hash/default-src.https.window.js.sub.headers new file mode 100644 index 00000000000000..3566b037308b70 --- /dev/null +++ b/content-security-policy/report-hash/default-src.https.window.js.sub.headers @@ -0,0 +1,3 @@ +Reporting-Endpoints: csp-endpoint="/reporting/resources/report.py?reportID={{$id:uuid()}}" +Content-Security-Policy: default-src 'self' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha256'; report-to csp-endpoint +Server-Timing: uuid;desc="{{$id}}",hash;desc="sha256-1XF/E08XndkoxwN6eIa5J89hYn3OVZ/UyB8BrU5jgzk=" diff --git a/content-security-policy/report-hash/multiple-policies.https.sub.html b/content-security-policy/report-hash/multiple-policies.https.sub.html new file mode 100644 index 00000000000000..ae4f88864d8266 --- /dev/null +++ b/content-security-policy/report-hash/multiple-policies.https.sub.html @@ -0,0 +1,18 @@ + + + + + Test that reports for same-origin subresources are sent with hashes + + + + + + + + + + + diff --git a/content-security-policy/report-hash/multiple-policies.https.sub.html.sub.headers b/content-security-policy/report-hash/multiple-policies.https.sub.html.sub.headers new file mode 100644 index 00000000000000..17c313da488b4a --- /dev/null +++ b/content-security-policy/report-hash/multiple-policies.https.sub.html.sub.headers @@ -0,0 +1,7 @@ +Reporting-Endpoints: csp-endpoint="/reporting/resources/report.py?reportID={{$id:uuid()}}" +Content-Security-Policy: script-src-elem 'self' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha256'; report-to csp-endpoint +Reporting-Endpoints: csp-endpoint2="/reporting/resources/report.py?reportID={{$id2:uuid()}}" +Content-Security-Policy: script-src-elem 'self' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha512'; report-to csp-endpoint2 +Server-Timing: uuid;desc="{{$id}}",hash;desc="sha256-1XF/E08XndkoxwN6eIa5J89hYn3OVZ/UyB8BrU5jgzk=" +Server-Timing: uuid2;desc="{{$id2}}",hash2;desc="sha512-hG4x56V5IhUUepZdYU/lX7UOQJ2M7f6ud2EI7os4JV3OwXSZ002P3zkb9tXQkjpOO8UbtjuEufvdcU67Qt2tlw==" + diff --git a/content-security-policy/report-hash/reportonly-default-src.https.window.js b/content-security-policy/report-hash/reportonly-default-src.https.window.js new file mode 100644 index 00000000000000..c8edc03fd3fe61 --- /dev/null +++ b/content-security-policy/report-hash/reportonly-default-src.https.window.js @@ -0,0 +1,3 @@ +// META: script=/reporting/resources/report-helper.js +// META: script=resources/report-hash-test-runner.sub.js +run_tests(); diff --git a/content-security-policy/report-hash/reportonly-default-src.https.window.js.sub.headers b/content-security-policy/report-hash/reportonly-default-src.https.window.js.sub.headers new file mode 100644 index 00000000000000..0490f22ed47e0a --- /dev/null +++ b/content-security-policy/report-hash/reportonly-default-src.https.window.js.sub.headers @@ -0,0 +1,3 @@ +Reporting-Endpoints: csp-endpoint="/reporting/resources/report.py?reportID={{$id:uuid()}}" +Content-Security-Policy-Report-Only: default-src 'self' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha256'; report-to csp-endpoint +Server-Timing: uuid;desc="{{$id}}",hash;desc="sha256-1XF/E08XndkoxwN6eIa5J89hYn3OVZ/UyB8BrU5jgzk=" diff --git a/content-security-policy/report-hash/reportonly-script-src-elem.https.window.js b/content-security-policy/report-hash/reportonly-script-src-elem.https.window.js new file mode 100644 index 00000000000000..c8edc03fd3fe61 --- /dev/null +++ b/content-security-policy/report-hash/reportonly-script-src-elem.https.window.js @@ -0,0 +1,3 @@ +// META: script=/reporting/resources/report-helper.js +// META: script=resources/report-hash-test-runner.sub.js +run_tests(); diff --git a/content-security-policy/report-hash/reportonly-script-src-elem.https.window.js.sub.headers b/content-security-policy/report-hash/reportonly-script-src-elem.https.window.js.sub.headers new file mode 100644 index 00000000000000..b7929547a09084 --- /dev/null +++ b/content-security-policy/report-hash/reportonly-script-src-elem.https.window.js.sub.headers @@ -0,0 +1,3 @@ +Reporting-Endpoints: csp-endpoint="/reporting/resources/report.py?reportID={{$id:uuid()}}" +Content-Security-Policy-Report-Only: script-src-elem 'self' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha256'; report-to csp-endpoint +Server-Timing: uuid;desc="{{$id}}",hash;desc="sha256-1XF/E08XndkoxwN6eIa5J89hYn3OVZ/UyB8BrU5jgzk=" diff --git a/content-security-policy/report-hash/reportonly-script-src-none.https.window.js b/content-security-policy/report-hash/reportonly-script-src-none.https.window.js new file mode 100644 index 00000000000000..d708e989b70c5a --- /dev/null +++ b/content-security-policy/report-hash/reportonly-script-src-none.https.window.js @@ -0,0 +1,4 @@ +// META: script=/reporting/resources/report-helper.js +// META: script=resources/report-hash-test-runner.sub.js +run_tests(); + diff --git a/content-security-policy/report-hash/reportonly-script-src-none.https.window.js.sub.headers b/content-security-policy/report-hash/reportonly-script-src-none.https.window.js.sub.headers new file mode 100644 index 00000000000000..9c6d3efd27489a --- /dev/null +++ b/content-security-policy/report-hash/reportonly-script-src-none.https.window.js.sub.headers @@ -0,0 +1,4 @@ +Reporting-Endpoints: csp-endpoint="/reporting/resources/report.py?reportID={{$id:uuid()}}" +Content-Security-Policy-Report-Only: script-src 'none' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha256'; report-to csp-endpoint +Server-Timing: uuid;desc="{{$id}}",hash;desc="sha256-1XF/E08XndkoxwN6eIa5J89hYn3OVZ/UyB8BrU5jgzk=" + diff --git a/content-security-policy/report-hash/reportonly-script-src.https.window.js b/content-security-policy/report-hash/reportonly-script-src.https.window.js new file mode 100644 index 00000000000000..c8edc03fd3fe61 --- /dev/null +++ b/content-security-policy/report-hash/reportonly-script-src.https.window.js @@ -0,0 +1,3 @@ +// META: script=/reporting/resources/report-helper.js +// META: script=resources/report-hash-test-runner.sub.js +run_tests(); diff --git a/content-security-policy/report-hash/reportonly-script-src.https.window.js.sub.headers b/content-security-policy/report-hash/reportonly-script-src.https.window.js.sub.headers new file mode 100644 index 00000000000000..ee7eb6f7f53b42 --- /dev/null +++ b/content-security-policy/report-hash/reportonly-script-src.https.window.js.sub.headers @@ -0,0 +1,3 @@ +Reporting-Endpoints: csp-endpoint="/reporting/resources/report.py?reportID={{$id:uuid()}}" +Content-Security-Policy-Report-Only: script-src 'self' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha256'; report-to csp-endpoint +Server-Timing: uuid;desc="{{$id}}",hash;desc="sha256-1XF/E08XndkoxwN6eIa5J89hYn3OVZ/UyB8BrU5jgzk=" diff --git a/content-security-policy/report-hash/resources/report-hash-test-runner.sub.js b/content-security-policy/report-hash/resources/report-hash-test-runner.sub.js new file mode 100644 index 00000000000000..f336cf14bfb586 --- /dev/null +++ b/content-security-policy/report-hash/resources/report-hash-test-runner.sub.js @@ -0,0 +1,129 @@ +function find_server_timing(name) { + const server_timing = performance.getEntriesByType("navigation")[0].serverTiming; + for (entry of server_timing) { + if (entry.name == name) { + return entry.description; + } + } + return null; +} + +const ORIGIN = "https://{{host}}:{{ports[https][0]}}"; +const REMOTE_ORIGIN = "https://{{hosts[alt][www]}}:{{ports[https][0]}}"; +const endpoint = `${ORIGIN}/reporting/resources/report.py`; +const id = find_server_timing("uuid"); +const id2 = find_server_timing("uuid2"); +const subresource_url = `${ORIGIN}/reporting/resources/comment.js`; +const crossorigin_subresource_url = `${REMOTE_ORIGIN}/reporting/resources/comment.js`; +const subresource_hash = find_server_timing("hash"); +const subresource_hash2 = find_server_timing("hash2"); +let counter = 0; + +function reporting_observer_setup(expected_url, expected_hash) { + return new Promise(resolve => { + new ReportingObserver((reports, observer) => { + assert_unreached(); + observer.disconnect(); + }, { types: ["csp-hash"] }).observe(); + step_timeout(resolve, 100); + }); +} + +async function check_reports(uuid, expected_hash, url) { + const reports = await pollReports(endpoint, uuid); + checkReportExists(reports, 'csp-hash', location.href); + const report = getReport(reports, 'csp-hash', location.href, url); + assert_not_equals(report, null); + assert_equals(report.body.hash, expected_hash); + assert_equals(report.body.type, "subresource"); + assert_equals(report.body.destination, "script"); +} + +function report_hash_test(url, populate_script_attributes, expected_hash, expected_hash2, description) { + promise_test(async t => { + const unique_subresource_url = `${url}?${++counter}`; + const observer_promise = reporting_observer_setup(unique_subresource_url, subresource_hash); + // Trigger a script load + await new Promise(resolve => { + const script = document.createElement('script'); + script.src = unique_subresource_url; + populate_script_attributes(script); + script.addEventListener('load', resolve); + document.head.appendChild(script); + }); + + await check_reports(id, expected_hash, unique_subresource_url); + if (id2) { + await check_reports(id2, expected_hash2, unique_subresource_url); + } + await observer_promise; + }, description); +} + +function no_report_test(create_element, description) { + promise_test(async t => { + const unique_subresource_url = `${subresource_url}?${++counter}`; + // Trigger a script load + await new Promise(resolve => { + const elem = create_element(unique_subresource_url); + elem.addEventListener('load', resolve); + elem.addEventListener('error', resolve); + document.head.appendChild(elem); + }); + + // Wait for report to be received. + const reports = await pollReports(endpoint, id); + const report = getReport(reports, 'csp-hash', location.href, unique_subresource_url); + assert_equals(report, null); + }, description); +}; + +function run_tests() { + report_hash_test(subresource_url, script => { + script.crossOrigin = "anonymous"; + }, subresource_hash, subresource_hash2, + "Reporting endpoints received hash for same-origin CORS script."); + + report_hash_test(subresource_url, script => { + }, subresource_hash, subresource_hash2, + "Reporting endpoints received hash for same-origin no-CORS script."); + + report_hash_test(crossorigin_subresource_url, script => { + script.crossOrigin = "anonymous"; + }, subresource_hash, subresource_hash2, + "Reporting endpoints received hash for cross-origin CORS script."); + + report_hash_test(crossorigin_subresource_url, script => { + }, /*expected_hash=*/"", /*expected_hash2=*/"", + "Reporting endpoints received no hash for cross-origin no-CORS script."); + + report_hash_test(subresource_url, script => { + script.crossOrigin = "anonymous"; + script.integrity = "sha512-hG4x56V5IhUUepZdYU/lX7UOQJ2M7f6ud2EI7os4JV3OwXSZ002P3zkb9tXQkjpOO8UbtjuEufvdcU67Qt2tlw=="; + }, subresource_hash, subresource_hash2, + "Reporting endpoints received the right hash for same-origin CORS script with integrity."); + + no_report_test(url => { + const script = document.createElement('script'); + script.src = url; + script.crossOrigin = "anonymous" + script.integrity = "sha256-foobar"; + return script; + }, "Reporting endpoints received no report for failed integrity check with sha256."); + + no_report_test(url => { + const script = document.createElement('script'); + script.src = url; + script.crossOrigin = "anonymous" + script.integrity = "sha512-foobar"; + return script; + }, "Reporting endpoints received no report for failed integrity check with sha512."); + + no_report_test(url => { + const link = document.createElement('link'); + link.href = url; + link.crossOrigin = "anonymous" + link.rel = "stylesheet" + return link; + }, "Reporting endpoints received no report for CORS stylesheet."); +} diff --git a/content-security-policy/report-hash/script-src-elem.https.window.js b/content-security-policy/report-hash/script-src-elem.https.window.js new file mode 100644 index 00000000000000..c8edc03fd3fe61 --- /dev/null +++ b/content-security-policy/report-hash/script-src-elem.https.window.js @@ -0,0 +1,3 @@ +// META: script=/reporting/resources/report-helper.js +// META: script=resources/report-hash-test-runner.sub.js +run_tests(); diff --git a/content-security-policy/report-hash/script-src-elem.https.window.js.sub.headers b/content-security-policy/report-hash/script-src-elem.https.window.js.sub.headers new file mode 100644 index 00000000000000..d9c04180310c85 --- /dev/null +++ b/content-security-policy/report-hash/script-src-elem.https.window.js.sub.headers @@ -0,0 +1,3 @@ +Reporting-Endpoints: csp-endpoint="/reporting/resources/report.py?reportID={{$id:uuid()}}" +Content-Security-Policy: script-src-elem 'self' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha256'; report-to csp-endpoint +Server-Timing: uuid;desc="{{$id}}",hash;desc="sha256-1XF/E08XndkoxwN6eIa5J89hYn3OVZ/UyB8BrU5jgzk=" diff --git a/content-security-policy/report-hash/script-src-sha512.https.window.js b/content-security-policy/report-hash/script-src-sha512.https.window.js new file mode 100644 index 00000000000000..c8edc03fd3fe61 --- /dev/null +++ b/content-security-policy/report-hash/script-src-sha512.https.window.js @@ -0,0 +1,3 @@ +// META: script=/reporting/resources/report-helper.js +// META: script=resources/report-hash-test-runner.sub.js +run_tests(); diff --git a/content-security-policy/report-hash/script-src-sha512.https.window.js.sub.headers b/content-security-policy/report-hash/script-src-sha512.https.window.js.sub.headers new file mode 100644 index 00000000000000..eaa0873582b78a --- /dev/null +++ b/content-security-policy/report-hash/script-src-sha512.https.window.js.sub.headers @@ -0,0 +1,3 @@ +Reporting-Endpoints: csp-endpoint="/reporting/resources/report.py?reportID={{$id:uuid()}}" +Content-Security-Policy: script-src 'self' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha512' 'report-sha384' 'report-sha256'; report-to csp-endpoint +Server-Timing: uuid;desc="{{$id}}",hash;desc="sha512-hG4x56V5IhUUepZdYU/lX7UOQJ2M7f6ud2EI7os4JV3OwXSZ002P3zkb9tXQkjpOO8UbtjuEufvdcU67Qt2tlw==" diff --git a/content-security-policy/report-hash/script-src.https.window.js b/content-security-policy/report-hash/script-src.https.window.js new file mode 100644 index 00000000000000..c8edc03fd3fe61 --- /dev/null +++ b/content-security-policy/report-hash/script-src.https.window.js @@ -0,0 +1,3 @@ +// META: script=/reporting/resources/report-helper.js +// META: script=resources/report-hash-test-runner.sub.js +run_tests(); diff --git a/content-security-policy/report-hash/script-src.https.window.js.sub.headers b/content-security-policy/report-hash/script-src.https.window.js.sub.headers new file mode 100644 index 00000000000000..bd92f728c858fb --- /dev/null +++ b/content-security-policy/report-hash/script-src.https.window.js.sub.headers @@ -0,0 +1,3 @@ +Reporting-Endpoints: csp-endpoint="/reporting/resources/report.py?reportID={{$id:uuid()}}" +Content-Security-Policy: script-src 'self' {{hosts[alt][www]}}:{{ports[https][0]}} 'unsafe-inline' 'report-sha256'; report-to csp-endpoint +Server-Timing: uuid;desc="{{$id}}",hash;desc="sha256-1XF/E08XndkoxwN6eIa5J89hYn3OVZ/UyB8BrU5jgzk=" diff --git a/reporting/resources/comment.js b/reporting/resources/comment.js new file mode 100644 index 00000000000000..7fa15a06da7798 --- /dev/null +++ b/reporting/resources/comment.js @@ -0,0 +1 @@ +// Ceci n'est pas un commentaire diff --git a/reporting/resources/comment.js.headers b/reporting/resources/comment.js.headers new file mode 100644 index 00000000000000..cb762eff806849 --- /dev/null +++ b/reporting/resources/comment.js.headers @@ -0,0 +1 @@ +Access-Control-Allow-Origin: * diff --git a/reporting/resources/report-helper.js b/reporting/resources/report-helper.js index 4d3c3fbdee800c..5b5438903de11c 100644 --- a/reporting/resources/report-helper.js +++ b/reporting/resources/report-helper.js @@ -36,3 +36,12 @@ function checkReportExists(reports, type, url) { } assert_unreached(`A report of ${type} from ${url} is not found.`); } + +function getReport(reports, type, document_url, subresource_url) { + for (const report of reports) { + if (report.type !== type) continue; + if (report.body.documentURL === document_url && report.body.subresourceURL == subresource_url) return report; + } + return null; +} +