| <!DOCTYPE html> |
| <title>CSP for subresource WebBundle (blocked cases)</title> |
| <link |
| rel="help" |
| href="https://github.com/WICG/webpackage/blob/main/explainers/subresource-loading.md" |
| /> |
| <meta |
| http-equiv="Content-Security-Policy" |
| content=" |
| script-src |
| urn: |
| https://web-platform.test:8444/resources/testharness.js |
| https://web-platform.test:8444/resources/testharnessreport.js |
| 'unsafe-inline'; |
| img-src |
| https://web-platform.test:8444/web-bundle/resources/wbn/subresource.wbn; |
| frame-src |
| urn:; |
| report-to |
| csp-group" |
| > |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <body> |
| <link rel="webbundle" href="../resources/wbn/subresource.wbn" |
| resources="https://web-platform.test:8444/web-bundle/resources/wbn/fail.png" /> |
| <link rel="webbundle" href="../resources/wbn/urn-uuid.wbn" |
| resources="urn:uuid:020111b3-437a-4c5c-ae07-adb6bbffb720 |
| urn:uuid:429fcc4e-0696-4bad-b099-ee9175f023ae" /> |
| <link rel="webbundle" href="../resources/wbn/uuid-in-package.wbn" |
| resources="uuid-in-package:020111b3-437a-4c5c-ae07-adb6bbffb720 |
| uuid-in-package:429fcc4e-0696-4bad-b099-ee9175f023ae" /> |
| <script> |
| const urn_bundle_url = 'https://web-platform.test:8444/web-bundle/resources/wbn/urn-uuid.wbn'; |
| const uuid_bundle_url = 'https://web-platform.test:8444/web-bundle/resources/wbn/uuid-in-package.wbn'; |
| |
| function expect_violation() { |
| return new Promise(resolve => { |
| document.addEventListener('securitypolicyviolation', (e) => { |
| e.stopPropagation(); |
| resolve(e); |
| }, {once: true}); |
| }); |
| } |
| |
| function getReportID() { |
| const cookies = document.cookie.split(';'); |
| for (var i = 0; i < cookies.length; i++) { |
| const name_value = cookies[i].split('='); |
| const cookieName = name_value[0].trim(); |
| if (cookieName === 'csp-blocked-report-id') { |
| return name_value[1].trim(); |
| } |
| } |
| } |
| |
| function sortReportsByEffectiveDirective(reports) { |
| reports.sort((report1, report2) => |
| report1.body.effectiveDirective.localeCompare(report2.body.effectiveDirective) |
| || report1.body.blockedURL.localeCompare(report2.body.blockedURL) |
| ); |
| } |
| |
| promise_test(async () => { |
| const p = expect_violation(); |
| const img = document.createElement('img'); |
| const error_promise = new Promise(resolve => { |
| img.onerror = resolve; |
| }); |
| img.src = 'https://web-platform.test:8444/web-bundle/resources/wbn/fail.png'; |
| document.body.appendChild(img); |
| const e = await p; |
| assert_equals(e.blockedURI, img.src); |
| await error_promise; |
| }, 'URL matching of CSP should be done based on the subresource URL, ' + |
| 'not on the bundle URL, when the subresource URL is HTTPS URL.'); |
| |
| const testCases = [ |
| { |
| prefix: 'urn:uuid:', |
| bundle_url: urn_bundle_url |
| }, |
| { |
| prefix: 'uuid-in-package:', |
| bundle_url: uuid_bundle_url |
| } |
| ]; |
| for (const params of testCases) { |
| |
| promise_test(async () => { |
| const urn_uuid = params.prefix + '020111b3-437a-4c5c-ae07-adb6bbffb720'; |
| const p = expect_violation(); |
| const script = document.createElement('script'); |
| script.src = urn_uuid; |
| document.body.appendChild(script); |
| const e = await p; |
| // Currently Chromium is reporting the bundle URL. |
| // TODO(crbug.com/1208659): Consider deeper integration with CSP for |
| // providing the both URLs. |
| assert_equals(e.blockedURI, params.bundle_url); |
| assert_equals(e.violatedDirective, 'script-src-elem'); |
| }, 'URL matching of script-src CSP should be done based on the bundle URL ' + |
| `when the subresource URL is ${params.prefix} URL.`); |
| |
| promise_test(async () => { |
| const urn_uuid = params.prefix + '429fcc4e-0696-4bad-b099-ee9175f023ae'; |
| const p = expect_violation(); |
| const iframe = document.createElement('iframe'); |
| iframe.src = urn_uuid; |
| const load_promise = new Promise(resolve => { |
| iframe.addEventListener('load', resolve); |
| }); |
| document.body.appendChild(iframe); |
| const e = await p; |
| // Currently Chromium is reporting the bundle URL. |
| // TODO(crbug.com/1208659): Consider deeper integration with CSP for |
| // providing the both URLs. |
| assert_equals(e.blockedURI, params.bundle_url); |
| assert_equals(e.violatedDirective, 'frame-src'); |
| |
| // Make sure that the blocked iframe load is finished. |
| await load_promise; |
| |
| // The blocked iframe is cross-origin. So accessing |
| // iframe.contentWindow.location should throw a SecurityError. |
| assert_throws_dom( |
| "SecurityError", |
| () => { iframe.contentWindow.location.href; }); |
| }, 'URL matching of frame-src CSP should be done based on the bundle URL ' + |
| `when the frame URL is ${params.prefix} URL.`); |
| } |
| |
| promise_test(async () => { |
| const retrieve_report_url = |
| "/reporting/resources/report.py?op=retrieve_report&timeout=3&reportID=" + |
| getReportID(); |
| const reports = await (await fetch(retrieve_report_url)).json(); |
| sortReportsByEffectiveDirective(reports); |
| |
| assert_equals(reports.length, 5, "Report count."); |
| |
| assert_equals(reports[0].body.blockedURL, urn_bundle_url); |
| assert_equals(reports[0].body.effectiveDirective, 'frame-src'); |
| assert_equals(reports[1].body.blockedURL, uuid_bundle_url); |
| assert_equals(reports[1].body.effectiveDirective, 'frame-src'); |
| |
| assert_equals( |
| reports[2].body.blockedURL, |
| 'https://web-platform.test:8444/web-bundle/resources/wbn/fail.png'); |
| assert_equals(reports[2].body.effectiveDirective, 'img-src',); |
| |
| assert_equals(reports[3].body.blockedURL, urn_bundle_url); |
| assert_equals(reports[3].body.effectiveDirective, 'script-src-elem'); |
| assert_equals(reports[4].body.blockedURL, uuid_bundle_url); |
| assert_equals(reports[4].body.effectiveDirective, 'script-src-elem'); |
| }, 'Check the CSP violation reports.'); |
| </script> |
| </body> |