tor-browser

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

dangling-markup-mitigation.tentative.html (4669B)


      1 <!DOCTYPE html>
      2 <script src="/resources/testharness.js"></script>
      3 <script src="/resources/testharnessreport.js"></script>
      4 <body>
      5 <script>
      6  function readableURL(url) {
      7    return url.replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
      8  }
      9 
     10  var should_load = [
     11    `/images/green-1x1.png`,
     12    `/images/gre\nen-1x1.png`,
     13    `/images/gre\ten-1x1.png`,
     14    `/images/gre\ren-1x1.png`,
     15    `/images/green-1x1.png?img=<`,
     16    `/images/green-1x1.png?img=&lt;`,
     17    `/images/green-1x1.png?img=%3C`,
     18    `/images/gr\neen-1x1.png?img=%3C`,
     19    `/images/gr\reen-1x1.png?img=%3C`,
     20    `/images/gr\teen-1x1.png?img=%3C`,
     21    `/images/green-1x1.png?img=&#10;`,
     22    `/images/gr\neen-1x1.png?img=&#10;`,
     23    `/images/gr\reen-1x1.png?img=&#10;`,
     24    `/images/gr\teen-1x1.png?img=&#10;`,
     25  ];
     26  should_load.forEach(url => async_test(t => {
     27    fetch(url)
     28      .then(t.step_func_done(r => {
     29        assert_equals(r.status, 200);
     30      }))
     31      .catch(t.unreached_func("Fetch should succeed."));
     32  }, "Fetch: " + readableURL(url)));
     33 
     34  var should_block = [
     35    `/images/gre\nen-1x1.png?img=<`,
     36    `/images/gre\ren-1x1.png?img=<`,
     37    `/images/gre\ten-1x1.png?img=<`,
     38    `/images/green-1x1.png?<\n=block`,
     39    `/images/green-1x1.png?<\r=block`,
     40    `/images/green-1x1.png?<\t=block`,
     41  ];
     42  should_block.forEach(url => async_test(t => {
     43    fetch(url)
     44      .then(t.unreached_func("Fetch should fail."))
     45      .catch(t.step_func_done());
     46  }, "Fetch: " + readableURL(url)));
     47 
     48 
     49  // For each of the following tests, we'll inject a frame containing the HTML we'd like to poke at
     50  // as a `srcdoc` attribute. Because we're injecting markup via `srcdoc`, we need to entity-escape
     51  // the content we'd like to treat as "raw" (e.g. `\n` => `&#10;`, `<` => `&lt;`), and
     52  // double-escape the "escaped" content.
     53  var rawBrace = "&lt;";
     54  var escapedBrace = "&amp;lt;";
     55  var rawNewline = "&#10;";
     56  var escapedNewline = "&amp;#10;";
     57 
     58  function appendFrameAndGetElement(test, frame) {
     59    return new Promise((resolve, reject) => {
     60      frame.onload = test.step_func(_ => {
     61        frame.onload = null;
     62        resolve(frame.contentDocument.querySelector('#dangling'));
     63      });
     64      document.body.appendChild(frame);
     65    });
     66  }
     67 
     68  function assert_img_loaded(test, frame) {
     69    appendFrameAndGetElement(test, frame)
     70      .then(test.step_func_done(img => {
     71        assert_equals(img.naturalHeight, 1, "Height");
     72        frame.remove();
     73      }));
     74  }
     75 
     76  function assert_img_not_loaded(test, frame) {
     77    appendFrameAndGetElement(test, frame)
     78      .then(test.step_func_done(img => {
     79        assert_equals(img.naturalHeight, 0, "Height");
     80        assert_equals(img.naturalWidth, 0, "Width");
     81      }));
     82  }
     83 
     84  function createFrame(markup) {
     85    var i = document.createElement('iframe');
     86    i.srcdoc = `${markup}sekrit`;
     87    return i;
     88  }
     89 
     90  // The following resources should not be blocked, as their URLs do not contain both a `\n` and `<`
     91  // character in the body of the URL.
     92  var should_load = [
     93    // Brace alone doesn't block:
     94    `<img id="dangling" src="/images/green-1x1.png?img=${rawBrace}b">`,
     95 
     96    // Newline alone doesn't block:
     97    `<img id="dangling" src="/images/green-1x1.png?img=${rawNewline}b">`,
     98 
     99    // Entity-escaped characters don't trigger blocking:
    100    `<img id="dangling" src="/images/green-1x1.png?img=${escapedNewline}b">`,
    101    `<img id="dangling" src="/images/green-1x1.png?img=${escapedBrace}b">`,
    102    `<img id="dangling" src="/images/green-1x1.png?img=${escapedNewline}b${escapedBrace}c">`,
    103 
    104    // Leading and trailing whitespace is stripped:
    105    `
    106      <img id="dangling" src="
    107        /images/green-1x1.png?img=
    108      ">
    109    `,
    110    `
    111      <img id="dangling" src="
    112        /images/green-1x1.png?img=${escapedBrace}
    113      ">
    114    `,
    115    `
    116      <img id="dangling" src="
    117        /images/green-1x1.png?img=${escapedNewline}
    118      ">
    119    `,
    120  ];
    121 
    122  should_load.forEach(markup => {
    123    async_test(t => {
    124      var i = createFrame(`${markup} <element attr="" another=''>`);
    125      assert_img_loaded(t, i);
    126    }, readableURL(markup));
    127  });
    128 
    129  // The following resources should be blocked, as their URLs contain both `\n` and `<` characters:
    130  var should_block = [
    131    `<img id="dangling" src="/images/green-1x1.png?img=${rawNewline}${rawBrace}b">`,
    132    `<img id="dangling" src="/images/green-1x1.png?img=${rawBrace}${rawNewline}b">`,
    133    `
    134      <img id="dangling" src="/images/green-1x1.png?img=
    135        ${rawBrace}
    136        ${rawNewline}b
    137      ">
    138    `,
    139  ];
    140 
    141  should_block.forEach(markup => {
    142    async_test(t => {
    143      var i = createFrame(`${markup}`);
    144      assert_img_not_loaded(t, i);
    145    }, readableURL(markup));
    146  });
    147 </script>