tor-browser

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

fetch.any.js (4410B)


      1 // META: global=window,dedicatedworker,sharedworker
      2 // META: script=/common/subset-tests-by-key.js
      3 // META: variant=?include=integrity-none
      4 // META: variant=?include=integrity-pass
      5 // META: variant=?include=integrity-fail
      6 // META: timeout=long
      7 
      8 // Given `{ digest: "...", body: "...", cors: true, type: "..." }`:
      9 function resourceURL(data) {
     10  let params = new URLSearchParams(data);
     11  return "./resource.py?" + params.toString();
     12 }
     13 
     14 const hello_world = "hello world";
     15 const hello_hashes = {
     16  "sha-256": "uU0nuZNNPgilLlLX2n2r+sSE7+N6U4DukIj3rOLvzek=",
     17  "sha-512": "MJ7MSJwS1utMxA9QyQLytNDtd+5RGnx6m808qG1M2G+YndNbxf9JlnDaNCVbRbDP2DDoH2Bdz33FVC6TrpzXbw=="
     18 };
     19 
     20 const dlrow_olleh = hello_world.split("").reverse().join("");
     21 const dlrow_hashes = {
     22  "sha-256": "vT+a3uWsoxRxVJEINKfH4XZpLqsneOzhFVY98Y3iIz0=",
     23  "sha-512": "N/peuevAy3l8KpS0bB6VTS8vc0fdAvjBJKYjVo2xb6sB6LpDfY6YlrXkWeeXGrP07UXDXEu1K3+SaUqMNjEkxQ=="
     24 };
     25 
     26 const EXPECT_BLOCKED = "block";
     27 const EXPECT_LOADED = "loaded";
     28 function generate_test(data, expectation, desc) {
     29  subsetTestByKey("integrity-none", promise_test, test => {
     30    let fetcher = fetch(resourceURL(data));
     31    if (expectation == EXPECT_BLOCKED) {
     32      return promise_rejects_js(test, TypeError, fetcher);
     33    } else {
     34      return fetcher.then(async r => {
     35        assert_equals(r.status, 200, "Response status is 200.");
     36        assert_equals(await r.text(), data.body);
     37      });
     38    }
     39  }, "No integrity metadata + " + desc);
     40 
     41  subsetTestByKey("integrity-pass", promise_test, test => {
     42    // Force CORS for the integrity check below:
     43    const data_with_cors = structuredClone(data);
     44    data_with_cors.cors = true;
     45 
     46    // The integrity check should pass, and nothing about the
     47    // `Unencoded-Digest` check should be affected.
     48    let fetcher = fetch(resourceURL(data_with_cors), { integrity: `sha256-${hello_hashes['sha-256']}`, mode: "cors" });
     49    if (expectation == EXPECT_BLOCKED) {
     50      return promise_rejects_js(test, TypeError, fetcher);
     51    } else {
     52      return fetcher.then(async r => {
     53        assert_equals(r.status, 200, "Response status is 200.");
     54        assert_equals(await r.text(), data.body);
     55      });
     56    }
     57  }, "Good integrity metadata + " + desc);
     58 
     59 
     60  subsetTestByKey("integrity-fail", promise_test, test => {
     61    // Force CORS for the integrity check below:
     62    const data_with_cors = structuredClone(data);
     63    data_with_cors.cors = true;
     64 
     65    // The integrity check should fail, so the resource should be blocked,
     66    // even with matching `Unencoded-Digest`s.
     67    let fetcher = fetch(resourceURL(data_with_cors), { integrity: `sha256-${dlrow_hashes['sha-256']}`, mode: "cors" });
     68    return promise_rejects_js(test, TypeError, fetcher);
     69  }, "Bad integrity metadata blocks everything, even: " + desc);
     70 }
     71 
     72 // No header.
     73 generate_test(
     74  { body: hello_world },
     75  EXPECT_LOADED,
     76  "No header: loads.");
     77 
     78 let good_header_list = [];
     79 let bad_header_list = [];
     80 let mixed_header_list = [];
     81 for (const key in hello_hashes) {
     82  let good_header = `${key}=:${hello_hashes[key]}:`;
     83  good_header_list.push(good_header);
     84  let bad_header = `${key}=:${dlrow_hashes[key]}:`;
     85  bad_header_list.push(bad_header);
     86  mixed_header_list.push(good_header, bad_header);
     87 
     88  // - Good single headers:
     89  generate_test({
     90      body: hello_world,
     91      digest: good_header
     92    },
     93    EXPECT_LOADED,
     94    `Good ${key} header: loads.`);
     95 
     96  // - Good multiple headers:
     97  generate_test({
     98      body: hello_world,
     99      digest: `${good_header},${good_header}`
    100    },
    101    EXPECT_LOADED,
    102    `Repeated ${key} header: loads.`);
    103 
    104  generate_test({
    105      body: hello_world,
    106      digest: good_header_list.join(",")
    107    },
    108    EXPECT_LOADED,
    109    `Multiple good headers (previous += ${key}): loads.`);
    110 
    111  // - Bad single headers:
    112  generate_test({
    113      body: hello_world,
    114      digest: bad_header
    115    },
    116    EXPECT_BLOCKED,
    117    `Bad ${key} header: blocked.`);
    118 
    119  // - Bad multiple headers:
    120  generate_test({
    121      body: hello_world,
    122      digest: `${bad_header},${bad_header}`
    123    },
    124    EXPECT_BLOCKED,
    125    `Repeated ${key} header: blocked.`);
    126 
    127  generate_test({
    128      body: hello_world,
    129      digest: bad_header_list.join(",")
    130    },
    131    EXPECT_BLOCKED,
    132    `Multiple bad headers (previous += ${key}): blocked.`);
    133 }
    134 
    135 // - Mixed headers.
    136 generate_test({
    137    body: hello_world,
    138    digest: mixed_header_list.join(","),
    139  },
    140  EXPECT_BLOCKED,
    141  `Mixed good and bad headers: blocked.`);