tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

script.window.js (4503B)


      1 // META: script=/common/subset-tests-by-key.js
      2 // META: variant=?include=integrity-none
      3 // META: variant=?include=integrity-pass
      4 // META: variant=?include=integrity-fail
      5 // META: timeout=long
      6 
      7 // Given `{ digest: "...", body: "...", cors: true }`:
      8 function scriptURL(data) {
      9  data.type = "application/javascript";
     10  let params = new URLSearchParams(data);
     11  return "./resource.py?" + params.toString();
     12 }
     13 
     14 const executable_body = "window.hello = `world`;";
     15 const unreached_body = "assert_unreached(`This code should not execute.`);";
     16 const executable_hashes = {
     17  "sha-256": "PZJ+9CdAAIacg7wfUe4t/RkDQJVKM0mCZ2K7qiRhHFc=",
     18  "sha-512": "6qaEeboWnnFooKiwqnorS3SbkLk5rZcqoSsgEeB97srB0WIH6hJk2QDevHAen7gym6/jW244Ogf5MhZMjPYFrA=="
     19 };
     20 const well_formed_but_incorrect_hashes = {
     21  "sha-256": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
     22  "sha-512": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
     23 };
     24 
     25 const EXPECT_BLOCKED = "block";
     26 const EXPECT_LOADED = "loaded";
     27 function generate_test(data, expectation, desc) {
     28  subsetTestByKey("integrity-none", async_test, t => {
     29    let s = document.createElement('script');
     30    s.src = scriptURL(data);
     31    if (expectation == EXPECT_BLOCKED) {
     32      s.onerror = t.step_func_done(e => {
     33        assert_equals("error", e.type);
     34      });
     35      s.onload = t.unreached_func("Script should not execute.");
     36    } else {
     37      s.onload = t.step_func_done(e => {
     38        assert_equals("load", e.type);
     39      });
     40      s.onerror = t.unreached_func("Script should not fail.");
     41    }
     42    document.body.appendChild(s);
     43  }, "No `integrity` attribute + " + desc);
     44 
     45  subsetTestByKey("integrity-pass", async_test, t => {
     46    let s = document.createElement('script');
     47    s.src = scriptURL(data);
     48    s.crossorigin = "anonymous";
     49    s.integrity = `sha256-${executable_hashes['sha-256']}`
     50    if (expectation == EXPECT_BLOCKED) {
     51      s.onerror = t.step_func_done(e => {
     52        assert_equals("error", e.type);
     53      });
     54      s.onload = t.unreached_func("Script should not execute.");
     55    } else {
     56      s.onload = t.step_func_done(e => {
     57        assert_equals("load", e.type);
     58      });
     59      s.onerror = t.unreached_func("Script should not fail.");
     60    }
     61    document.body.appendChild(s);
     62  }, "Matching `integrity` attribute + " + desc);
     63 
     64  subsetTestByKey("integrity-fail", async_test, t => {
     65    let s = document.createElement('script');
     66    s.src = scriptURL(data);
     67    s.crossorigin = "anonymous";
     68    s.integrity = `sha512-${well_formed_but_incorrect_hashes['sha-512']}`
     69    s.onerror = t.step_func_done(e => {
     70      assert_equals("error", e.type);
     71    });
     72    s.onload = t.unreached_func("Script should not execute.");
     73    document.body.appendChild(s);
     74  }, "Mismatching `integrity` attribute always blocks: " + desc);
     75 }
     76 
     77 // No header.
     78 generate_test(
     79  { body: executable_body },
     80  EXPECT_LOADED,
     81  "No header: loads.");
     82 
     83 let good_header_list = [];
     84 let bad_header_list = [];
     85 let mixed_header_list = [];
     86 for (const key in executable_hashes) {
     87  let good_header = `${key}=:${executable_hashes[key]}:`;
     88  good_header_list.push(good_header);
     89  let bad_header = `${key}=:${well_formed_but_incorrect_hashes[key]}:`;
     90  bad_header_list.push(bad_header);
     91  mixed_header_list.push(good_header, bad_header);
     92 
     93  // - Good single headers:
     94  generate_test({
     95      body: executable_body,
     96      digest: good_header
     97    },
     98    EXPECT_LOADED,
     99    `Good ${key} header: loads.`);
    100 
    101  // - Good multiple headers:
    102  generate_test({
    103      body: executable_body,
    104      digest: `${good_header},${good_header}`
    105    },
    106    EXPECT_LOADED,
    107    `Repeated ${key} header: loads.`);
    108 
    109  generate_test({
    110      body: executable_body,
    111      digest: good_header_list.join(",")
    112    },
    113    EXPECT_LOADED,
    114    `Multiple good headers (previous += ${key}): loads.`);
    115 
    116  // - Bad single headers:
    117  generate_test({
    118      body: executable_body,
    119      digest: bad_header
    120    },
    121    EXPECT_BLOCKED,
    122    `Bad ${key} header: blocked.`);
    123 
    124  // - Bad multiple headers:
    125  generate_test({
    126      body: executable_body,
    127      digest: `${bad_header},${bad_header}`
    128    },
    129    EXPECT_BLOCKED,
    130    `Repeated ${key} header: blocked.`);
    131 
    132  generate_test({
    133      body: executable_body,
    134      digest: bad_header_list.join(",")
    135    },
    136    EXPECT_BLOCKED,
    137    `Multiple bad headers (previous += ${key}): blocked.`);
    138 }
    139 
    140 // - Mixed headers.
    141 generate_test({
    142    body: executable_body,
    143    digest: mixed_header_list.join(","),
    144  },
    145  EXPECT_BLOCKED,
    146  `Mixed good and bad headers: blocked.`);