tor-browser

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

dangling-markup-mitigation-allowed-apis.https.html (3455B)


      1 <!DOCTYPE html>
      2 <meta name="timeout" content="long">
      3 <script src="/resources/testharness.js"></script>
      4 <script src="/resources/testharnessreport.js"></script>
      5 <body>
      6 <script>
      7  const blank = 'about:blank';
      8  const dangling_url = 'resources/empty.html?\n<';
      9  const navigation_api_calls = [
     10    `window.open(\`${dangling_url}\`,'_self')`,
     11    `location.replace(\`${dangling_url}\`)`,
     12  ];
     13 
     14  function get_requests(test, worker, expected) {
     15    return new Promise((resolve, reject) => {
     16      let didTimeout = false;
     17      test.step_timeout(() => {
     18        didTimeout = true;
     19        reject("get_requests timed out");
     20      }, 1000);
     21      navigator.serviceWorker.addEventListener('message', function onMsg(evt) {
     22        if (evt.data.size >= expected) {
     23          navigator.serviceWorker.removeEventListener('message', onMsg);
     24          resolve(evt.data);
     25        } else if (!didTimeout) {
     26          worker.postMessage("");
     27        }
     28      });
     29      worker.postMessage("");
     30    });
     31  }
     32 
     33  navigation_api_calls.forEach(call => {
     34    async_test(t => {
     35      const iframe =
     36        document.body.appendChild(document.createElement('iframe'));
     37      t.step(() => {
     38        iframe.contentWindow.eval(call);
     39        t.step_timeout(() => {
     40          assert_false(iframe.contentWindow.location.href.endsWith(blank));
     41          t.done();
     42        }, 500);
     43      });
     44    }, `Does not block ${call}`);
     45  });
     46 
     47  const dangling_resource = "404?type=text/javascript&\n<"
     48  const dangling_resource_expected = "404?type=text/javascript&%3C"
     49  const api_calls = [
     50    [`const xhr = new XMLHttpRequest();
     51     xhr.open("GET", \`${"xhr" + dangling_resource}\`);
     52     xhr.send(null);`, "xhr"],
     53    [`new EventSource(\`${"EventSource" + dangling_resource}\`)`,"EventSource"],
     54    [`fetch(\`${"fetch" + dangling_resource}\`).catch(()=>{})`, "fetch"],
     55    [`new Worker(\`${"Worker" + dangling_resource}\`)`, "Worker"],
     56    [`let text = \`try{importScripts(\\\`${location.href + "/../importScripts" + dangling_resource}\\\`)}catch(e){}\`;
     57     let blob = new Blob([text], {type : 'text/javascript'});
     58     let url = URL.createObjectURL(blob);
     59     new Worker(url)`, "importScripts"],
     60 
     61  ];
     62 
     63  let iframe, registration;
     64  promise_test(async t => {
     65    iframe = document.createElement('iframe');
     66    iframe.src = "resources/empty.html";
     67    document.body.appendChild(iframe);
     68    await new Promise(resolve => iframe.onload = resolve);
     69    registration = await navigator.serviceWorker.register('service-worker.js');
     70    if (!iframe.contentWindow.navigator.serviceWorker.controller)
     71      await new Promise(resolve => iframe.contentWindow.navigator.serviceWorker.oncontrollerchange = resolve);
     72  }, "Setup controlled frame");
     73 
     74  let number_api_calls = 0;
     75  api_calls.forEach(call => {
     76    promise_test(async t => {
     77      iframe.contentWindow.eval(call[0]);
     78      const requests = await get_requests(t, registration.active, number_api_calls + 1);
     79      assert_equals(Array.from(requests)[number_api_calls], call[1] + dangling_resource_expected);
     80      number_api_calls++;
     81    }, `Does not block ${call[1]}`);
     82  });
     83  promise_test(async () => {
     84    iframe.remove();
     85    registration.unregister();
     86  }, "Clean up iframe");
     87 
     88  async_test(t => {
     89    let url = new URL(location.origin + "/" + dangling_url);
     90    // Newlines are removed by the URL parser.
     91    assert_true(url.href.endsWith(encodeURI(dangling_url.replace("\n",""))));
     92    t.done();
     93  }, `Does not block new URL()`);
     94 </script>