| <!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> |
| <script type="webbundle"> |
| { |
| "source": "../resources/wbn/subresource.wbn", |
| "resources": ["https://web-platform.test:8444/web-bundle/resources/wbn/fail.png"] |
| } |
| </script> |
| <script type="webbundle"> |
| { |
| "source": "../resources/wbn/uuid-in-package.wbn", |
| "resources": ["uuid-in-package:020111b3-437a-4c5c-ae07-adb6bbffb720", |
| "uuid-in-package:429fcc4e-0696-4bad-b099-ee9175f023ae"] |
| } |
| </script> |
| <script> |
| 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: "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, 3, "Report count."); |
| |
| assert_equals(reports[0].body.blockedURL, uuid_bundle_url); |
| assert_equals(reports[0].body.effectiveDirective, "frame-src"); |
| |
| assert_equals( |
| reports[1].body.blockedURL, |
| "https://web-platform.test:8444/web-bundle/resources/wbn/fail.png" |
| ); |
| assert_equals(reports[1].body.effectiveDirective, "img-src"); |
| |
| assert_equals(reports[2].body.blockedURL, uuid_bundle_url); |
| assert_equals(reports[2].body.effectiveDirective, "script-src-elem"); |
| }, "Check the CSP violation reports."); |
| </script> |
| </body> |