tor-browser

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

test_iframe_sandbox.html (7840B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <!--
      4 https://bugzilla.mozilla.org/show_bug.cgi?id=671389
      5 Bug 671389 - Implement CSP sandbox directive
      6 -->
      7 <head>
      8  <meta charset="utf-8">
      9  <title>Tests for Bug 671389</title>
     10  <script src="/tests/SimpleTest/SimpleTest.js"></script>
     11  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
     12 </head>
     13 <script type="application/javascript">
     14 
     15  SimpleTest.waitForExplicitFinish();
     16 
     17  // Check if two sandbox flags are the same, ignoring case-sensitivity.
     18  // getSandboxFlags returns a list of sandbox flags (if any) or
     19  // null if the flag is not set.
     20  // This function checks if two flags are the same, i.e., they're
     21  // either not set or have the same flags.
     22  function eqFlags(a, b) {
     23    if (a === null && b === null) { return true; }
     24    if (a === null || b === null) { return false; }
     25    if (a.length !== b.length) {  return false; }
     26    var a_sorted = a.map(function(e) { return e.toLowerCase(); }).sort();
     27    var b_sorted = b.map(function(e) { return e.toLowerCase(); }).sort();
     28    for (var i in a_sorted) {
     29      if (a_sorted[i] !== b_sorted[i]) {
     30        return false;
     31      }
     32    }
     33    return true;
     34  }
     35 
     36  // Get the sandbox flags of document doc.
     37  // If the flag is not set sandboxFlagsAsString returns null,
     38  // this function also returns null.
     39  // If the flag is set it may have some flags; in this case
     40  // this function returns the (potentially empty) list of flags.
     41  function getSandboxFlags(doc) {
     42    var flags = doc.sandboxFlagsAsString;
     43    if (flags === null) { return null; }
     44    return flags? flags.split(" "):[];
     45  }
     46 
     47  // Constructor for a CSP sandbox flags test. The constructor
     48  // expectes a description 'desc' and set of options 'opts':
     49  //  - sandboxAttribute: [null] or string corresponding to the iframe sandbox attributes
     50  //  - csp: [null] or string corresponding to the CSP sandbox flags
     51  //  - cspReportOnly: [null] or string corresponding to the CSP report-only sandbox flags
     52  //  - file: [null] or string corresponding to file the server should serve
     53  // Above, we use [brackets] to denote default values.
     54  function CSPFlagsTest(desc, opts) {
     55    function ifundef(x, v) {
     56      return (x !== undefined) ? x : v;
     57    }
     58 
     59    function intersect(as, bs) { // Intersect two csp attributes:
     60      as = as === null ? null
     61                       : as.split(' ').filter(function(x) { return !!x; });
     62      bs = bs === null ? null
     63                       : bs.split(' ').filter(function(x) { return !!x; });
     64 
     65      if (as === null) { return bs; }
     66      if (bs === null) { return as; }
     67 
     68      var cs = [];
     69      as.forEach(function(a) {
     70        if (a && bs.includes(a))
     71          cs.push(a);
     72      });
     73      return cs;
     74    }
     75 
     76    this.desc     = desc || "Untitled test";
     77    this.attr     = ifundef(opts.sandboxAttribute, null);
     78    this.csp      = ifundef(opts.csp, null);
     79    this.cspRO    = ifundef(opts.cspReportOnly, null);
     80    this.file     = ifundef(opts.file, null);
     81    this.expected = intersect(this.attr, this.csp);
     82  }
     83 
     84  // Return function that checks that the actual flags are the same as the
     85  // expected flags
     86  CSPFlagsTest.prototype.checkFlags = function(iframe) {
     87    var this_ = this;
     88    return function() {
     89      try {
     90        var actual = getSandboxFlags(SpecialPowers.wrap(iframe).contentDocument);
     91        ok(eqFlags(actual, this_.expected),
     92           this_.desc + ' - expected: "' + this_.expected + '", got: "' + actual + '"');
     93      } catch (e) {
     94        ok(false,
     95           this_.desc + ' - expected: "' + this_.expected + '", failed with: "' + e + '"');
     96      }
     97      runNextTest();
     98     };
     99  };
    100 
    101  // Set the iframe src and sandbox attribute
    102  CSPFlagsTest.prototype.runTest = function () {
    103    var iframe = document.createElement('iframe');
    104    document.getElementById("content").appendChild(iframe);
    105    iframe.onload = this.checkFlags(iframe);
    106 
    107    // set sandbox attribute
    108    if (this.attr === null) {
    109      iframe.removeAttribute('sandbox');
    110    } else {
    111      iframe.sandbox = this.attr;
    112    }
    113 
    114    // set query string
    115    var src = 'http://mochi.test:8888/tests/dom/security/test/csp/file_testserver.sjs';
    116 
    117    var delim = '?';
    118 
    119    if (this.csp !== null) {
    120      src += delim + 'csp=' + escape('sandbox ' + this.csp);
    121      delim = '&';
    122    }
    123 
    124    if (this.cspRO !== null) {
    125      src += delim + 'cspRO=' + escape('sandbox ' + this.cspRO);
    126      delim = '&';
    127    }
    128 
    129    if (this.file !== null) {
    130      src += delim + 'file=' + escape(this.file);
    131      delim = '&';
    132    }
    133 
    134    iframe.src = src;
    135    iframe.width = iframe.height = 10;
    136 
    137  }
    138 
    139  testCases = [
    140    {
    141      desc: "Test 1: Header should not override attribute",
    142      sandboxAttribute: "",
    143      csp: "allow-forms aLLOw-POinter-lock alLOW-popups aLLOW-SAME-ORIGin ALLOW-SCRIPTS allow-top-navigation"
    144    },
    145    {
    146      desc: "Test 2: Attribute should not override header",
    147      sandboxAttribute: "sandbox allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation",
    148      csp: ""
    149    },
    150    {
    151      desc: "Test 3: Header and attribute intersect",
    152      sandboxAttribute: "allow-same-origin allow-scripts",
    153      csp: "allow-forms allow-same-origin allow-scripts"
    154    },
    155    {
    156      desc: "Test 4: CSP sandbox sets the right flags (pt 1)",
    157      csp: "alLOW-FORms ALLOW-pointer-lock allow-popups allow-same-origin allow-scripts ALLOW-TOP-NAVIGation"
    158    },
    159    {
    160      desc: "Test 5: CSP sandbox sets the right flags (pt 2)",
    161      csp: "allow-same-origin allow-TOP-navigation"
    162    },
    163    {
    164      desc: "Test 6: CSP sandbox sets the right flags (pt 3)",
    165      csp: "allow-FORMS ALLOW-scripts"
    166    },
    167    {
    168      desc: "Test 7: CSP sandbox sets the right flags (pt 4)",
    169      csp: ""
    170    },
    171    {
    172      desc: "Test 8: CSP sandbox sets the right flags (pt 5)",
    173      csp: null
    174    },
    175    {
    176      desc: "Test 9: Read-only header should not override attribute",
    177      sandboxAttribute: "",
    178      cspReportOnly: "allow-forms ALLOW-pointer-lock allow-POPUPS allow-same-origin ALLOW-scripts allow-top-NAVIGATION"
    179    },
    180    {
    181      desc: "Test 10: Read-only header should not override CSP header",
    182      csp: "allow-forms allow-scripts",
    183      cspReportOnly: "allow-forms aLlOw-PoInTeR-lOcK aLLow-pOPupS aLLoW-SaME-oRIgIN alLow-scripts allow-tOp-navigation"
    184    },
    185    {
    186      desc: "Test 11: Read-only header should not override attribute or CSP header",
    187      sandboxAttribute: "allow-same-origin allow-scripts",
    188      csp: "allow-forms allow-same-origin allow-scripts",
    189      cspReportOnly: "allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation"
    190    },
    191    {
    192      desc: "Test 12: CSP sandbox not affected by document.write()",
    193      csp: "allow-scripts",
    194      file: 'tests/dom/security/test/csp/file_iframe_sandbox_document_write.html'
    195    },
    196  ].map(function(t) { return (new CSPFlagsTest(t.desc,t)); });
    197 
    198 
    199  var testCaseIndex = 0;
    200 
    201  // Track ok messages from iframes
    202  var childMessages = 0;
    203  var totalChildMessages = 1;
    204 
    205 
    206  // Check to see if we ran all the tests and received all messges
    207  // from child iframes. If so, finish.
    208  function tryFinish() {
    209    if (testCaseIndex === testCases.length && childMessages === totalChildMessages){
    210      SimpleTest.finish();
    211    }
    212  }
    213 
    214  function runNextTest() {
    215 
    216    tryFinish();
    217 
    218    if (testCaseIndex < testCases.length) {
    219      testCases[testCaseIndex].runTest();
    220      testCaseIndex++;
    221    }
    222  }
    223 
    224  function receiveMessage(event) {
    225    ok(event.data.ok, event.data.desc);
    226    childMessages++;
    227    tryFinish();
    228  }
    229 
    230  window.addEventListener("message", receiveMessage);
    231 
    232  addLoadEvent(runNextTest);
    233 </script>
    234 <body>
    235  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=671389">Mozilla Bug 671389</a> - Implement CSP sandbox directive
    236  <p id="display"></p>
    237  <div id="content">
    238  </div>
    239 </body>
    240 </html>