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 })();