tor-browser

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

disallowed-navigations.https.html (4430B)


      1 <!DOCTYPE html>
      2 <title>Fenced frame disallowed navigations</title>
      3 <meta name="timeout" content="long">
      4 <script src="/resources/testharness.js"></script>
      5 <script src="/resources/testharnessreport.js"></script>
      6 <script src="/common/dispatcher/dispatcher.js"></script>
      7 <script src="/common/get-host-info.sub.js"></script>
      8 <script src="/common/utils.js"></script>
      9 <script src="resources/utils.js"></script>
     10 <script src="/fetch/local-network-access/resources/support.sub.js"></script>
     11 
     12 <body>
     13 
     14 <script>
     15 // Baseline tests:
     16 //   - Embedder can navigate iframe to blob: URL
     17 //   - Embedder can navigate iframe to data: URL
     18 //   - Same-origin embedder can navigate iframe to javascript: URL
     19 //   - Embedder can navigate iframe to http: URL
     20 // Fenced frame tests:
     21 //   - Embedder cannot navigate fenced frame to blob: URL
     22 //   - Embedder cannot navigate fenced frame to data: URL
     23 //   - Same-origin embedder cannot navigate fenced frame to
     24 //     javascript: URL
     25 //   - Embedder cannot navigate fenced frame to http: URL
     26 
     27 // Fenced frames are always put in the public IP address space which is the
     28 // least privileged. In case a navigation to a local data: URL or blob: URL
     29 // resource is allowed, they would only be able to fetch things that are *also*
     30 // in the public IP address space. So for the document described by these local
     31 // URLs, we'll set them up to only communicate back to the outer page via
     32 // resources obtained in the public address space.
     33 const kPublicUtils = resolveUrl("resources/utils.js", Server.HTTPS_PUBLIC);
     34 
     35 // These are just baseline tests asserting that this test's machinery to load
     36 // blob:, data:, and javascript: URLs work properly in contexts where they are
     37 // expected to.
     38 promise_test(async () => {
     39  const key = token();
     40  attachIFrame(`data:text/html, ${createLocalSource(key, kPublicUtils)}`);
     41  const result = await nextValueFromServer(key);
     42  assert_equals(result, "LOADED");
     43 }, "iframe data: URL");
     44 
     45 promise_test(async () => {
     46  const key = token();
     47  const blobURL = URL.createObjectURL(
     48      new Blob([`${createLocalSource(key, kPublicUtils)}`],
     49               {type: 'text/html'}));
     50  attachIFrame(blobURL);
     51  const result = await nextValueFromServer(key);
     52  assert_equals(result, "LOADED");
     53 }, "iframe blob: URL");
     54 
     55 promise_test(async () => {
     56  const iframe = attachIFrameContext();
     57  iframe.src = "javascript:window.jsURLExecuted = true;"
     58  await iframe.execute(async () => {
     59    assert_equals(window.jsURLExecuted, true);
     60  });
     61 }, "iframe javascript: URL");
     62 
     63 // The following tests ensure that an embedder cannot navigate a fenced frame
     64 // to:
     65 //   - data: URLs
     66 //   - blob: URLs
     67 //   - javascript: URLs
     68 //   - http: URLs
     69 function getTimeoutPromise(t) {
     70  return new Promise(resolve =>
     71      t.step_timeout(() => resolve("NOT LOADED"), 2000));
     72 }
     73 
     74 promise_test(async t => {
     75  const key = token();
     76  attachFencedFrame(`data:text/html, ${createLocalSource(key, kPublicUtils)}`);
     77  const loaded_promise = nextValueFromServer(key);
     78  const result = await Promise.any([loaded_promise, getTimeoutPromise(t)]);
     79  assert_equals(result, "NOT LOADED");
     80 }, `fenced frame data: URL`);
     81 
     82 promise_test(async t => {
     83  const key = token();
     84  const blobURL = URL.createObjectURL(
     85      new Blob([`${createLocalSource(key, kPublicUtils)}`],
     86               {type: 'text/html'}));
     87  attachFencedFrame(blobURL);
     88  const loaded_promise = nextValueFromServer(key);
     89  const result = await Promise.any([loaded_promise, getTimeoutPromise(t)]);
     90  assert_equals(result, "NOT LOADED");
     91 }, `fenced frame blob: URL`);
     92 
     93 promise_test(async t => {
     94  const fencedframe = attachFencedFrameContext();
     95  fencedframe.src = "javascript:window.jsURLExecuted = true;"
     96  // Just in case the javascript URL executes asynchronously, let's wait for
     97  // it.
     98  await getTimeoutPromise(t);
     99  await fencedframe.execute(async () => {
    100    assert_equals(window.jsURLExecuted, undefined);
    101  });
    102 }, `fenced frame javascript: URL`);
    103 
    104 promise_test(async t => {
    105  const key = token();
    106  let http_url = new URL("resources/embeddee.html",
    107      get_host_info().HTTP_ORIGIN + location.pathname);
    108  http_url = generateURL(http_url, [key]);
    109  assert_equals(http_url.protocol, "http:");
    110  const fencedframe = attachFencedFrame(http_url);
    111  const loaded_promise = nextValueFromServer(key);
    112  const result = await Promise.any([loaded_promise, getTimeoutPromise(t)]);
    113  assert_equals(result, "NOT LOADED");
    114 }, `fenced frame http: URL`);
    115 
    116 </script>
    117 
    118 </body>