| // META: script=/common/subset-tests-by-key.js |
| // META: variant=?include=integrity-none |
| // META: variant=?include=integrity-pass |
| // META: variant=?include=integrity-fail |
| // META: timeout=long |
| |
| // Given `{ digest: "...", body: "...", cors: true }`: |
| function scriptURL(data) { |
| data.type = "application/javascript"; |
| let params = new URLSearchParams(data); |
| return "./resource.py?" + params.toString(); |
| } |
| |
| const executable_body = "window.hello = `world`;"; |
| const unreached_body = "assert_unreached(`This code should not execute.`);"; |
| const executable_hashes = { |
| "sha-256": "PZJ+9CdAAIacg7wfUe4t/RkDQJVKM0mCZ2K7qiRhHFc=", |
| "sha-512": "6qaEeboWnnFooKiwqnorS3SbkLk5rZcqoSsgEeB97srB0WIH6hJk2QDevHAen7gym6/jW244Ogf5MhZMjPYFrA==" |
| }; |
| const well_formed_but_incorrect_hashes = { |
| "sha-256": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", |
| "sha-512": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" |
| }; |
| |
| const EXPECT_BLOCKED = "block"; |
| const EXPECT_LOADED = "loaded"; |
| function generate_test(data, expectation, desc) { |
| subsetTestByKey("integrity-none", async_test, t => { |
| let s = document.createElement('script'); |
| s.src = scriptURL(data); |
| if (expectation == EXPECT_BLOCKED) { |
| s.onerror = t.step_func_done(e => { |
| assert_equals("error", e.type); |
| }); |
| s.onload = t.unreached_func("Script should not execute."); |
| } else { |
| s.onload = t.step_func_done(e => { |
| assert_equals("load", e.type); |
| }); |
| s.onerror = t.unreached_func("Script should not fail."); |
| } |
| document.body.appendChild(s); |
| }, "No `integrity` attribute + " + desc); |
| |
| subsetTestByKey("integrity-pass", async_test, t => { |
| let s = document.createElement('script'); |
| s.src = scriptURL(data); |
| s.crossorigin = "anonymous"; |
| s.integrity = `sha256-${executable_hashes['sha-256']}` |
| if (expectation == EXPECT_BLOCKED) { |
| s.onerror = t.step_func_done(e => { |
| assert_equals("error", e.type); |
| }); |
| s.onload = t.unreached_func("Script should not execute."); |
| } else { |
| s.onload = t.step_func_done(e => { |
| assert_equals("load", e.type); |
| }); |
| s.onerror = t.unreached_func("Script should not fail."); |
| } |
| document.body.appendChild(s); |
| }, "Matching `integrity` attribute + " + desc); |
| |
| subsetTestByKey("integrity-fail", async_test, t => { |
| let s = document.createElement('script'); |
| s.src = scriptURL(data); |
| s.crossorigin = "anonymous"; |
| s.integrity = `sha512-${well_formed_but_incorrect_hashes['sha-512']}` |
| s.onerror = t.step_func_done(e => { |
| assert_equals("error", e.type); |
| }); |
| s.onload = t.unreached_func("Script should not execute."); |
| document.body.appendChild(s); |
| }, "Mismatching `integrity` attribute always blocks: " + desc); |
| } |
| |
| // No header. |
| generate_test( |
| { body: executable_body }, |
| EXPECT_LOADED, |
| "No header: loads."); |
| |
| let good_header_list = []; |
| let bad_header_list = []; |
| let mixed_header_list = []; |
| for (const key in executable_hashes) { |
| let good_header = `${key}=:${executable_hashes[key]}:`; |
| good_header_list.push(good_header); |
| let bad_header = `${key}=:${well_formed_but_incorrect_hashes[key]}:`; |
| bad_header_list.push(bad_header); |
| mixed_header_list.push(good_header, bad_header); |
| |
| // - Good single headers: |
| generate_test({ |
| body: executable_body, |
| digest: good_header |
| }, |
| EXPECT_LOADED, |
| `Good ${key} header: loads.`); |
| |
| // - Good multiple headers: |
| generate_test({ |
| body: executable_body, |
| digest: `${good_header},${good_header}` |
| }, |
| EXPECT_LOADED, |
| `Repeated ${key} header: loads.`); |
| |
| generate_test({ |
| body: executable_body, |
| digest: good_header_list.join(",") |
| }, |
| EXPECT_LOADED, |
| `Multiple good headers (previous += ${key}): loads.`); |
| |
| // - Bad single headers: |
| generate_test({ |
| body: executable_body, |
| digest: bad_header |
| }, |
| EXPECT_BLOCKED, |
| `Bad ${key} header: blocked.`); |
| |
| // - Bad multiple headers: |
| generate_test({ |
| body: executable_body, |
| digest: `${bad_header},${bad_header}` |
| }, |
| EXPECT_BLOCKED, |
| `Repeated ${key} header: blocked.`); |
| |
| generate_test({ |
| body: executable_body, |
| digest: bad_header_list.join(",") |
| }, |
| EXPECT_BLOCKED, |
| `Multiple bad headers (previous += ${key}): blocked.`); |
| } |
| |
| // - Mixed headers. |
| generate_test({ |
| body: executable_body, |
| digest: mixed_header_list.join(","), |
| }, |
| EXPECT_BLOCKED, |
| `Mixed good and bad headers: blocked.`); |