File: dangling-markup-mitigation-allowed-apis.https.html

package info (click to toggle)
firefox 144.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,637,504 kB
  • sloc: cpp: 7,576,692; javascript: 6,430,831; ansic: 3,748,119; python: 1,398,978; xml: 628,810; asm: 438,679; java: 186,194; sh: 63,212; makefile: 19,159; objc: 13,086; perl: 12,986; yacc: 4,583; cs: 3,846; pascal: 3,448; lex: 1,720; ruby: 1,003; exp: 762; php: 436; lisp: 258; awk: 247; sql: 66; sed: 53; csh: 10
file content (94 lines) | stat: -rw-r--r-- 3,455 bytes parent folder | download | duplicates (15)
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<!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(test, worker, expected) {
    return new Promise((resolve, reject) => {
      let didTimeout = false;
      test.step_timeout(() => {
        didTimeout = true;
        reject("get_requests timed out");
      }, 1000);
      navigator.serviceWorker.addEventListener('message', function onMsg(evt) {
        if (evt.data.size >= expected) {
          navigator.serviceWorker.removeEventListener('message', onMsg);
          resolve(evt.data);
        } else if (!didTimeout) {
          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 dangling_resource_expected = "404?type=text/javascript&%3C"
  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"],

  ];

  let iframe, registration;
  promise_test(async t => {
    iframe = document.createElement('iframe');
    iframe.src = "resources/empty.html";
    document.body.appendChild(iframe);
    await new Promise(resolve => iframe.onload = resolve);
    registration = await navigator.serviceWorker.register('service-worker.js');
    if (!iframe.contentWindow.navigator.serviceWorker.controller)
      await new Promise(resolve => iframe.contentWindow.navigator.serviceWorker.oncontrollerchange = resolve);
  }, "Setup controlled frame");

  let number_api_calls = 0;
  api_calls.forEach(call => {
    promise_test(async t => {
      iframe.contentWindow.eval(call[0]);
      const requests = await get_requests(t, registration.active, number_api_calls + 1);
      assert_equals(Array.from(requests)[number_api_calls], call[1] + dangling_resource_expected);
      number_api_calls++;
    }, `Does not block ${call[1]}`);
  });
  promise_test(async () => {
    iframe.remove();
    registration.unregister();
  }, "Clean up iframe");

  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>