Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test has a WPT meta file that expects 11 subtest issues.
- This WPT test may be referenced by the following Test IDs:
- /subresource-integrity/integrity-policy/script.https.html - WPT Dashboard Interop Dashboard
<!doctype html>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/dispatcher/dispatcher.js"></script>
<script src="/common/utils.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="/reporting/resources/report-helper.js"></script>
<body>
<script>
const {ORIGIN} = get_host_info();
const getAbsoluteUrl = url => {
return new URL(url, window.location.href).href;
}
const check_report = async (reporting_endpoint, reporting_uuid, iframe_url, url, report_only) => {
const reports = await pollReports(reporting_endpoint, reporting_uuid);
const abs_iframe_url = getAbsoluteUrl(iframe_url);
checkReportExists(reports, 'integrity-violation', abs_iframe_url);
const abs_blocked_url = getAbsoluteUrl(url);
const report = getReport(reports, 'integrity-violation', abs_iframe_url, abs_blocked_url);
assert_not_equals(report, null);
assert_equals(report.body.documentURL, abs_iframe_url);
assert_equals(report.body.blockedURL, abs_blocked_url);
assert_equals(report.body.destination, "script");
assert_equals(report.body.reportOnly, report_only);
};
const blob = new Blob([`window.ran=true;`],
{ type: 'application/javascript' });
const blob_url = URL.createObjectURL(blob);
// Generated using https://sha2.it/ed25519.html (In Chrome Canary, with Experimental Web Platform Features enabled)
const signature = encodeURIComponent(
'header(Unencoded-Digest, sha-384=:tqyFpeo21WFM8HDeUtLqH20GUq\/q3D1R6mqTzW3RtyTZ3dAYZJhC1wUcnkgOE2ak:)' +
'|header(Signature-Input, signature=\\("unencoded-digest";sf\\); keyid="JrQLj5P\/89iXES9+vFgrIy29clF9CC\/oPPsw3c5D0bs="; tag="sri")' +
'|header(Signature, signature=:qM19uLskHm2TQG5LJcH/hY0n0BWWzYOJztVWYlwk0cZb3u0JdgUMre1J4Jn8Tma0x2u5/kPBfbXRMbB+X+vTBw==:)');
const test_cases = [
{
description: "Ensure that a script without integrity did not run",
url: "/content-security-policy/resources/ran.js",
cross_origin: true,
integrity: "",
policy_violation: true,
block: true,
endpoints: true,
expected: {blocked: ORIGIN + "/content-security-policy/resources/ran.js", ran: false },
},
{
description: "Ensure that a script with unknown integrity algorithm did not run",
url: "/content-security-policy/resources/ran.js",
cross_origin: true,
integrity: "foobar-AAAAAAAAAAAAAAAAAAAa",
policy_violation: true,
block: true,
endpoints: true,
expected: {blocked: ORIGIN + "/content-security-policy/resources/ran.js", ran: false },
},
{
description: "Ensure that a script without integrity algorithm runs and gets reported in report-only mode",
url: "/content-security-policy/resources/ran.js",
cross_origin: true,
integrity: "",
policy_violation: true,
block: false,
endpoints: true,
expected: {blocked: ORIGIN + "/content-security-policy/resources/ran.js", ran: true },
},
{
description: "Ensure that a no-cors script gets blocked",
url: "/content-security-policy/resources/ran.js",
cross_origin: false,
integrity: "sha384-tqyFpeo21WFM8HDeUtLqH20GUq/q3D1R6mqTzW3RtyTZ3dAYZJhC1wUcnkgOE2ak",
policy_violation: true,
block: true,
endpoints: true,
expected: {blocked: ORIGIN + "/content-security-policy/resources/ran.js", ran: false },
},
{
description: "Ensure that ReportingObserver gets called without endpoints",
url: "/content-security-policy/resources/ran.js",
cross_origin: false,
integrity: "sha384-tqyFpeo21WFM8HDeUtLqH20GUq/q3D1R6mqTzW3RtyTZ3dAYZJhC1wUcnkgOE2ak",
policy_violation: true,
block: true,
endpoints: false,
expected: {blocked: ORIGIN + "/content-security-policy/resources/ran.js", ran: false },
},
{
description: "Ensure that a script with integrity runs",
url: "/content-security-policy/resources/ran.js",
cross_origin: true,
integrity: "sha384-tqyFpeo21WFM8HDeUtLqH20GUq/q3D1R6mqTzW3RtyTZ3dAYZJhC1wUcnkgOE2ak",
policy_violation: false,
block: true,
endpoints: true,
expected: {blocked: "", ran: true },
},
{
description: "Ensure that a script with signature integrity runs",
url: "/content-security-policy/resources/ran.js?pipe=" + signature,
cross_origin: true,
integrity: "ed25519-JrQLj5P/89iXES9+vFgrIy29clF9CC/oPPsw3c5D0bs=",
policy_violation: false,
block: true,
endpoints: true,
expected: {blocked: "", ran: true },
},
{
description: "Ensure that a data URI script with no integrity runs",
url: "data:application/javascript,window.ran=true",
cross_origin: true,
integrity: "",
policy_violation: false,
block: true,
endpoints: true,
expected: {blocked: "", ran: true },
},
{
description: "Ensure that a no-CORS data URI script with no integrity runs",
url: "data:application/javascript,window.ran=true",
cross_origin: false,
integrity: "",
policy_violation: false,
block: true,
endpoints: true,
expected: {blocked: "", ran: true },
},
{
description: "Ensure that a blob URL script with no integrity runs",
url: blob_url,
cross_origin: true,
integrity: "",
policy_violation: false,
block: true,
endpoints: true,
expected: {blocked: "", ran: true },
},
{
description: "Ensure that a no-CORS blob URL script with no integrity runs",
url: blob_url,
cross_origin: false,
integrity: "",
policy_violation: false,
block: true,
endpoints: true,
expected: {blocked: "", ran: true },
}
];
test_cases.map(test_case => {
promise_test(async () => {
const REMOTE_EXECUTOR =
`/common/dispatcher/remote-executor.html?pipe=`;
const iframe_uuid = token();
const params = new URLSearchParams(location.search);
if (params.get('type') === "report") {
if (test_case.expected.blocked) {
return;
}
header_name += "-Report-Only";
}
const reporting_uuid_1 = token();
const reporting_uuid_2 = token();
const reporting_uuid_3 = token();
const reporting_endpoint = `${ORIGIN}/reporting/resources/report.py`;
let header = "";
if (test_case.block) {
header +=
`header(Integrity-Policy,blocked-destinations=\\(script\\)\\, endpoints=\\(integrity-endpoint-1 integrity-endpoint-2\\))`;
}
header +=
`|header(Integrity-Policy-Report-Only,blocked-destinations=\\(script\\)\\, endpoints=\\(integrity-endpoint-3\\))`;
if (test_case.endpoints) {
header +=
`|header(Reporting-Endpoints, integrity-endpoint-1=\"${reporting_endpoint}?reportID=${reporting_uuid_1}\"\\, ` +
`integrity-endpoint-2=\"${reporting_endpoint}?reportID=${reporting_uuid_2}\"\\, ` +
`integrity-endpoint-3=\"${reporting_endpoint}?reportID=${reporting_uuid_3}\")`;
}
const iframe_url = `${REMOTE_EXECUTOR}${encodeURIComponent(header)}&uuid=${iframe_uuid}`;
const iframe = document.createElement('iframe');
iframe.src = iframe_url;
document.body.appendChild(iframe);
// Execute code directly from the iframe.
const ctx = new RemoteContext(iframe_uuid);
const result = await ctx.execute_script(async (test_case) => {
window.ran = false;
let report_observed_promise;
if (test_case.policy_violation) {
report_observed_promise = new Promise(r => {
(new ReportingObserver((reports, observer) => {
reports.forEach(report => {
if (report.body.blockedURL.endsWith(test_case.url)) {
r(report.body);
observer.disconnect();
}
});
})).observe('integrity-violation');
});
}
// Load the script
await new Promise(resolve => {
const script = document.createElement('script');
if (test_case.cross_origin) {
script.crossOrigin="anonymous";
}
if (test_case.integrity) {
script.integrity = test_case.integrity;
}
script.onload = resolve;
script.onerror = resolve;
script.src = test_case.url;
document.body.appendChild(script);
});
const report_body = await report_observed_promise;
return { body: report_body, ran: window.ran };
}, [test_case]);
assert_equals(result.ran, test_case.expected.ran);
if (test_case.policy_violation) {
assert_equals(result.body.blockedURL, test_case.expected.blocked);
assert_true(result.body.documentURL.endsWith(iframe_url));
assert_equals(result.body.destination, "script");
assert_equals(result.body.reportOnly, !test_case.block);
}
if (test_case.endpoints && test_case.policy_violation) {
if (test_case.block) {
await check_report(reporting_endpoint, reporting_uuid_1, iframe_url, test_case.url, !test_case.block);
await check_report(reporting_endpoint, reporting_uuid_2, iframe_url, test_case.url, !test_case.block);
}
await check_report(reporting_endpoint, reporting_uuid_3, iframe_url, test_case.url, true);
}
}, test_case.description);
});
</script>