summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/fetch/security/dangling-markup/dangling-markup-mitigation-allowed-apis.tentative.https.html
blob: 428decfc583d8268ae36bc1ddf832d21c30ea6a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<!DOCTYPE html>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script>
  const blank = 'about:blank';
  const dangling_url = 'resources/empty.html?\n<';
  const navigation_api_calls = [
    `window.open(\`${dangling_url}\`,'_self')`,
    `location.replace(\`${dangling_url}\`)`,
  ];

  function get_requests(worker, expected) {
    return new Promise(resolve => {
      navigator.serviceWorker.addEventListener('message', function onMsg(evt) {
        if (evt.data.size >= expected) {
          navigator.serviceWorker.removeEventListener('message', onMsg);
          resolve(evt.data);
        } else {
          worker.postMessage("");
        }
      });
      worker.postMessage("");
    });
  }

  navigation_api_calls.forEach(call => {
    async_test(t => {
      const iframe =
        document.body.appendChild(document.createElement('iframe'));
      t.step(() => {
        iframe.contentWindow.eval(call);
        t.step_timeout(() => {
          assert_false(iframe.contentWindow.location.href.endsWith(blank));
          t.done();
        }, 500);
      });
    }, `Does not block ${call}`);
  });

  const dangling_resource = "404?type=text/javascript&\n<"
  const api_calls = [
    [`const xhr = new XMLHttpRequest();
     xhr.open("GET", \`${"xhr" + dangling_resource}\`);
     xhr.send(null);`, "xhr"],
    [`new EventSource(\`${"EventSource" + dangling_resource}\`)`,"EventSource"],
    [`fetch(\`${"fetch" + dangling_resource}\`).catch(()=>{})`, "fetch"],
    [`new Worker(\`${"Worker" + dangling_resource}\`)`, "Worker"],
    [`let text = \`try{importScripts(\\\`${location.href + "/../importScripts" + dangling_resource}\\\`)}catch(e){}\`;
     let blob = new Blob([text], {type : 'text/javascript'});
     let url = URL.createObjectURL(blob);
     new Worker(url)`, "importScripts"],

  ];

  navigator.serviceWorker.register('service-worker.js');
  const iframe = document.createElement('iframe');
  iframe.src = "resources/empty.html";
  document.body.appendChild(iframe);
  api_calls.forEach(call => {
    promise_test(t => {
      return new Promise(resolve => {
        navigator.serviceWorker.ready.then(t.step_func(registration => {
          iframe.contentWindow.eval(call[0]);
          get_requests(registration.active, 0).then(t.step_func(requests => {
            resolve(assert_true(requests.has(call[1] + dangling_resource)));
          }));
        }));
      });
    }, `Does not block ${call[1]}`);
  });

  async_test(t => {
    let url = new URL(location.origin + "/" + dangling_url);
    // Newlines are removed by the URL parser.
    assert_true(url.href.endsWith(encodeURI(dangling_url.replace("\n",""))));
    t.done();
  }, `Does not block new URL()`);
</script>