tor-browser

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

script-url-allowed-by-hash.https.html (11040B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 
      4 <head>
      5  <title>Scripts should be allowed if a matching URL hash is present</title>
      6  <script src="/common/get-host-info.sub.js"></script>
      7  <script src='/resources/testharness.js'></script>
      8  <script src='/resources/testharnessreport.js'c'></script>
      9  <script src='support/util.js' nonce='abc'></script>
     10 </head>
     11 
     12 <body>
     13  <script>
     14    const { ORIGIN, REMOTE_ORIGIN } = get_host_info();
     15    const scriptUrl = new URL("./support/externalScript.js", document.location).toString();
     16    const dynamicScriptUrl = new URL("./support/add_dynamic_script.js", document.location).toString();
     17    const redirectUrl = new URL("/common/redirect.py?location=" + scriptUrl, document.location).toString();
     18 
     19    // This is the hash of the string 'foo.js':
     20    const wrongHash = "LJVNbdCJGjP5027dMuLOQeMEiDI8JvMr5zMiXqW5tzs=";
     21 
     22    function get_iframe_url(test_type, policy, script_url) {
     23      return test_type == "header" ?
     24        `support/iframe.sub.html?pipe=header(Content-Security-Policy,${policy})&script_url=${script_url}`:
     25        `support/iframe_meta.sub.html?policy=${policy}&script_url=${script_url}`;
     26    }
     27 
     28    function get_iframe_url_with_inline_script(test_type, policy) {
     29      return test_type == "header" ?
     30        `support/iframe_inline.sub.html?pipe=header(Content-Security-Policy,${policy})`:
     31        `support/iframe_inline_meta.sub.html?policy=${policy}`;
     32    }
     33 
     34    function get_iframe_url_in_child_dir(test_type, policy, script_url) {
     35      return test_type == "header" ?
     36        `support/child_dir/iframe.sub.html?pipe=header(Content-Security-Policy,${policy})&script_url=${script_url}`:
     37        `support/child_dir/iframe_meta.sub.html?policy=${policy}&script_url=${script_url}`;
     38    }
     39 
     40    for (let test_type of ["header", "metatag"]) {
     41 
     42      promise_test(async t => {
     43        const scriptUrlHash = await sha256ofURL(scriptUrl);
     44        const policy = `script-src 'nonce-forinlinescript' 'url-sha256-${scriptUrlHash}'`
     45 
     46        let frame = document.createElement('iframe');
     47        frame.src = get_iframe_url(test_type, policy, 'externalScript.js');
     48        document.body.appendChild(frame);
     49 
     50        const msgEvent = await new Promise(resolve => window.onmessage = resolve);
     51        assert_equals(msgEvent.data, 'SCRIPT_RAN');
     52      }, "script-src should allow script by its url hash - " + test_type);
     53 
     54      promise_test(async t => {
     55        const policy = `script-src 'nonce-forinlinescript' 'url-sha256-${wrongHash}' ${ORIGIN} ${REMOTE_ORIGIN}`
     56 
     57        let frame = document.createElement('iframe');
     58        frame.src = get_iframe_url(test_type, policy, 'externalScript.js');
     59        document.body.appendChild(frame);
     60 
     61        const msgEvent = await new Promise(resolve => window.onmessage = resolve);
     62        assert_equals(msgEvent.data, 'CSP_VIOLATION');
     63      }, "A parseable url-hash should ignore hostname allowlists - " + test_type);
     64 
     65      // TODO(crbug.com/414459670): Add a test with an invalid url-hash.
     66 
     67      promise_test(async t => {
     68        const scriptUrlHash = await sha256ofURL(scriptUrl);
     69        const policy = `default-src 'nonce-forinlinescript' 'url-sha256-${scriptUrlHash}'`
     70 
     71        let frame = document.createElement('iframe');
     72        frame.src = get_iframe_url(test_type, policy, 'externalScript.js');
     73        document.body.appendChild(frame);
     74 
     75        const msgEvent = await new Promise(resolve => window.onmessage = resolve);
     76        assert_equals(msgEvent.data, 'SCRIPT_RAN');
     77      }, "default-src should allow script by its url hash - " + test_type);
     78 
     79      promise_test(async t => {
     80        const scriptUrlHash = await sha256ofURL(scriptUrl);
     81        const policy = `script-src-elem 'nonce-forinlinescript' 'url-sha256-${scriptUrlHash}'`
     82 
     83        let frame = document.createElement('iframe');
     84        frame.src = get_iframe_url(test_type, policy, 'externalScript.js');
     85        document.body.appendChild(frame);
     86 
     87        const msgEvent = await new Promise(resolve => window.onmessage = resolve);
     88        assert_equals(msgEvent.data, 'SCRIPT_RAN');
     89      }, "script-src-elem should allow script by its url hash - " + test_type);
     90 
     91      promise_test(async t => {
     92        // externalScript.js isn't allowlisted:
     93        const dynamicScriptUrlHash = await sha256ofURL(dynamicScriptUrl);
     94        const policy = `script-src 'nonce-forinlinescript' 'url-sha256-${dynamicScriptUrlHash}'`
     95 
     96        let frame = document.createElement('iframe');
     97        frame.src = get_iframe_url(test_type, policy, 'add_dynamic_script.js');
     98        document.body.appendChild(frame);
     99 
    100        const msgEvent = await new Promise(resolve => window.onmessage = resolve);
    101        assert_equals(msgEvent.data, 'CSP_VIOLATION');
    102      }, "url hashes should not allow dynamically inserted script transitively - " + test_type);
    103 
    104      promise_test(async t => {
    105        const scriptUrlHash = await sha256ofURL(scriptUrl);
    106        const dynamicScriptUrlHash = await sha256ofURL(dynamicScriptUrl);
    107        const policy = `script-src 'nonce-forinlinescript' 'url-sha256-${dynamicScriptUrlHash}' 'url-sha256-${scriptUrlHash}'`
    108 
    109        let frame = document.createElement('iframe');
    110        frame.src = get_iframe_url(test_type, policy, 'add_dynamic_script.js');
    111        document.body.appendChild(frame);
    112 
    113        const msgEvent = await new Promise(resolve => window.onmessage = resolve);
    114        assert_equals(msgEvent.data, 'SCRIPT_RAN');
    115      }, "url hashes should allow dynamically inserted script if allowlisted - " + test_type);
    116 
    117      promise_test(async t => {
    118        // externalScript.js isn't explicitly allowlisted but it should be allowed:
    119        const redirectUrlHash = await sha256ofURL(redirectUrl);
    120        const policy = `script-src 'nonce-forinlinescript' 'url-sha256-${redirectUrlHash}'`
    121 
    122        let frame = document.createElement('iframe');
    123        frame.src = get_iframe_url(test_type, policy, redirectUrl);
    124        document.body.appendChild(frame);
    125 
    126        const msgEvent = await new Promise(resolve => window.onmessage = resolve);
    127        assert_equals(msgEvent.data, 'SCRIPT_RAN');
    128      }, "url hashes should allow redirected scripts - " + test_type);
    129 
    130      // Tests for strict-dynamic-url keyword:
    131 
    132      promise_test(async t => {
    133        // add_dynamic_script.js isn't allowlisted but strict-dynamic-url should allow it:
    134        const dynamicScriptUrlHash = await sha256ofURL(dynamicScriptUrl);
    135        const policy = `script-src 'nonce-forinlinescript' 'strict-dynamic-url' 'url-sha256-${dynamicScriptUrlHash}'`
    136 
    137        let frame = document.createElement('iframe');
    138        frame.src = get_iframe_url(test_type, policy, 'add_dynamic_script.js');
    139        document.body.appendChild(frame);
    140 
    141        const msgEvent = await new Promise(resolve => window.onmessage = resolve);
    142        assert_equals(msgEvent.data, 'SCRIPT_RAN');
    143      }, "dynamically inserted parser-inserted script should be allowed if strict-dynamic-url is present - " + test_type);
    144 
    145      promise_test(async t => {
    146        // externalScript.js isn't allowlisted but strict-dynamic-url should allow it:
    147        const scriptUrlHash = await sha256ofURL(scriptUrl);
    148        // This is the hash of the inline script that dynamically inserts externalScript.js.
    149        const inlineScriptHash = "F8UqObF6TSi2W4dDcDzAOAplJkYovBE6JpJjsZJy5HA=";
    150        const policy = `script-src 'nonce-forinlinescript' 'strict-dynamic-url' 'sha256-${inlineScriptHash}'`
    151 
    152        let frame = document.createElement('iframe');
    153        frame.src = get_iframe_url_with_inline_script(test_type, policy);
    154        document.body.appendChild(frame);
    155 
    156        const msgEvent = await new Promise(resolve => window.onmessage = resolve);
    157        assert_equals(msgEvent.data, 'SCRIPT_RAN');
    158      }, "dynamically inserted script inserted by an inline script should be allowed if strict-dynamic-url is present - " + test_type);
    159 
    160      // Relative URL tests:
    161 
    162      promise_test(async t => {
    163        const scriptUrlHash = await sha256ofURL("externalScript.js");
    164        const policy = `script-src 'nonce-forinlinescript' 'url-sha256-${scriptUrlHash}'`
    165 
    166        let frame = document.createElement('iframe');
    167        frame.src = get_iframe_url(test_type, policy, 'externalScript.js');
    168        document.body.appendChild(frame);
    169 
    170        const msgEvent = await new Promise(resolve => window.onmessage = resolve);
    171        assert_equals(msgEvent.data, 'SCRIPT_RAN');
    172      }, "script-src should allow script by its relative url's hash - " + test_type);
    173 
    174      promise_test(async t => {
    175        const scriptUrlHash = await sha256ofURL("child_dir/externalScript.js");
    176        const policy = `script-src 'nonce-forinlinescript' 'url-sha256-${scriptUrlHash}'`
    177 
    178        let frame = document.createElement('iframe');
    179        frame.src = get_iframe_url(test_type, policy, 'child_dir/externalScript.js');
    180        document.body.appendChild(frame);
    181 
    182        const msgEvent = await new Promise(resolve => window.onmessage = resolve);
    183        assert_equals(msgEvent.data, 'SCRIPT_RAN');
    184      }, "script-src should allow script by its relative url's hash in child directory - " + test_type);
    185 
    186      promise_test(async t => {
    187        const scriptUrlHash = await sha256ofURL("./externalScript.js");
    188        const policy = `script-src 'nonce-forinlinescript' 'url-sha256-${scriptUrlHash}'`
    189 
    190        let frame = document.createElement('iframe');
    191        frame.src = get_iframe_url(test_type, policy, 'externalScript.js');
    192        document.body.appendChild(frame);
    193 
    194        const msgEvent = await new Promise(resolve => window.onmessage = resolve);
    195        assert_equals(msgEvent.data, 'CSP_VIOLATION');
    196      }, "script-src should disallow script with incorrect relative url hash - " + test_type);
    197 
    198      // Relative URL tests with iframes in support/child_dir.
    199 
    200      promise_test(async t => {
    201        const scriptUrlHash = await sha256ofURL("externalScript.js");
    202        const policy = `script-src 'nonce-forinlinescript' 'url-sha256-${scriptUrlHash}'`
    203 
    204        let frame = document.createElement('iframe');
    205        frame.src = get_iframe_url_in_child_dir(test_type, policy, 'externalScript.js');
    206        document.body.appendChild(frame);
    207 
    208        const msgEvent = await new Promise(resolve => window.onmessage = resolve);
    209        assert_equals(msgEvent.data, 'SCRIPT_RAN');
    210      }, "script-src should allow script by its relative url's hash in an iframe in child dir - " + test_type);
    211 
    212      promise_test(async t => {
    213        const scriptUrlHash = await sha256ofURL("../externalScript.js");
    214        const policy = `script-src 'nonce-forinlinescript' 'url-sha256-${scriptUrlHash}'`
    215 
    216        let frame = document.createElement('iframe');
    217        frame.src = get_iframe_url_in_child_dir(test_type, policy, '../externalScript.js');
    218        document.body.appendChild(frame);
    219 
    220        const msgEvent = await new Promise(resolve => window.onmessage = resolve);
    221        assert_equals(msgEvent.data, 'SCRIPT_RAN');
    222      }, "script-src should allow script in parent dir by its relative url's hash in an iframe in child dir - " + test_type);
    223 
    224    }
    225 
    226  </script>
    227 </body>
    228 
    229 </html>