tor-browser

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

checkReport.sub.js (5820B)


      1 (function () {
      2 
      3  // Get values from the substitution engine.
      4  // We can't just pull these from the document context
      5  // because this script is intended to be transcluded into
      6  // another document, and we want the GET values used to request it,
      7  // not the values for the including document
      8 
      9  // XXX these are unencoded, so there's an unavoidable
     10  // injection vulnerability in constructing this file...
     11  // need to upgrade the template engine.
     12  var reportField  = "{{GET[reportField]}}";
     13  var reportValue  = "{{GET[reportValue]}}";
     14  var reportExists = "{{GET[reportExists]}}";
     15  var noCookies = "{{GET[noCookies]}}";
     16  var reportCookieName = "{{GET[reportCookieName]}}"
     17  var testName = "{{GET[testName]}}"
     18  var cookiePresent = "{{GET[cookiePresent]}}"
     19  var reportCount = "{{GET[reportCount]}}"
     20 
     21  var location = window.location;
     22  if (reportCookieName == "") {
     23    // fallback on test file name if cookie name not specified
     24    reportCookieName = location.pathname.split('/')[location.pathname.split('/').length - 1].split('.')[0];
     25  }
     26 
     27  var reportID = "{{GET[reportID]}}";
     28 
     29  if (reportID == "") {
     30    var cookies = document.cookie.split(';');
     31    for (var i = 0; i < cookies.length; i++) {
     32      var cookieName = cookies[i].split('=')[0].trim();
     33      var cookieValue = cookies[i].split('=')[1].trim();
     34 
     35      if (cookieName == reportCookieName) {
     36        reportID = cookieValue;
     37        var cookieToDelete = cookieName + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=" + document.location.pathname.substring(0, document.location.pathname.lastIndexOf('/') + 1);
     38        document.cookie = cookieToDelete;
     39        break;
     40      }
     41    }
     42  }
     43 
     44  // There is no real way to test (in this particular layer) that a CSP report
     45  // has *not* been sent, at least not without some major reworks and
     46  // involvement from all the platform participants. So the current "solution"
     47  // is to wait for some reasonable amount of time and if no report has been
     48  // received to conclude that no report has been generated. These timeouts must
     49  // not exceed the test timeouts set by vendors otherwise the test would fail.
     50  var timeout = document.querySelector("meta[name=timeout][content=long]") ? 20 : 3;
     51  var reportLocation = location.protocol + "//" + location.host + "/reporting/resources/report.py?op=retrieve_report&timeout=" + timeout + "&reportID=" + reportID;
     52 
     53  if (testName == "") testName = "Violation report status OK.";
     54  var reportTest = async_test(testName);
     55 
     56  function assert_field_value(field, value, field_name) {
     57    assert_true(field.indexOf(value.split(" ")[0]) != -1,
     58                field_name + " value of  \"" + field + "\" did not match " +
     59                value.split(" ")[0] + ".");
     60  }
     61 
     62  reportTest.step(function () {
     63 
     64    var report = new XMLHttpRequest();
     65    report.onload = reportTest.step_func(function () {
     66      var data = JSON.parse(report.responseText);
     67 
     68      if (data.error) {
     69        assert_equals("false", reportExists, data.error);
     70      } else {
     71        if (reportExists === "false") {
     72          assert_equals(data.length, 0,
     73                        "CSP report sent, but not expecting one.");
     74        } else {
     75          // With the 'report-uri' directive, the report is contained in
     76          // `data[0]["csp-report"]`. With the 'report-to' directive, the report
     77          // is contained in `data[0]["body"]`.
     78          const reportBody = data[0]["body"]
     79                ? data[0]["body"]
     80                : data[0]["csp-report"];
     81 
     82          assert_true(reportBody !== undefined,
     83                      "No CSP report sent, but expecting one.");
     84          // Firefox expands 'self' or origins in a policy to the actual origin value
     85          // so "www.example.com" becomes "http://www.example.com:80".
     86          // Accomodate this by just testing that the correct directive name
     87          // is reported, not the details...
     88 
     89          if (reportBody[reportField] !== undefined) {
     90            assert_field_value(reportBody[reportField], reportValue, reportField);
     91          } else {
     92            assert_equals(reportField, "", "Expected report field could not be found in report.");
     93          }
     94        }
     95      }
     96 
     97      reportTest.done();
     98    });
     99 
    100    report.open("GET", reportLocation, true);
    101    report.send();
    102  });
    103 
    104  if (noCookies || cookiePresent) {
    105      var cookieTest = async_test("Test report cookies.");
    106      var cookieReport = new XMLHttpRequest();
    107      cookieReport.onload = cookieTest.step_func(function () {
    108        var data = JSON.parse(cookieReport.responseText);
    109        if (noCookies) {
    110          assert_equals(data.reportCookies, "None", "Report should not contain any cookies");
    111        }
    112 
    113        if (cookiePresent) {
    114          assert_true(data.reportCookies.hasOwnProperty(cookiePresent), "Report should contain cookie: " + cookiePresent);
    115        }
    116        cookieTest.done();
    117      });
    118      var cReportLocation = location.protocol + "//" + location.host + "/reporting/resources/report.py?op=retrieve_cookies&timeout=" + timeout + "&reportID=" + reportID;
    119      cookieReport.open("GET", cReportLocation, true);
    120      cookieReport.send();
    121  }
    122 
    123  if (reportCount != "") {
    124      var reportCountTest = async_test("Test number of sent reports.");
    125      var reportCountReport = new XMLHttpRequest();
    126      reportCountReport.onload = reportCountTest.step_func(function () {
    127        var data = JSON.parse(reportCountReport.responseText);
    128 
    129        assert_equals(data.report_count, +reportCount, "Report count was not what was expected.");
    130 
    131        reportCountTest.done();
    132      });
    133      var cReportLocation = location.protocol + "//" + location.host + "/reporting/resources/report.py?op=retrieve_count&timeout=" + timeout + "&reportID=" + reportID;
    134      reportCountReport.open("GET", cReportLocation, true);
    135      reportCountReport.send();
    136  }
    137 
    138 })();