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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
|
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Bug 1139297 - Implement CSP upgrade-insecure-requests directive</title>
<!-- Including SimpleTest.js so we can use waitForExplicitFinish !-->
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<iframe style="width:100%;" id="testframe"></iframe>
<script class="testbody" type="text/javascript">
/* Description of the test:
* We load resources (img, script, sytle, etc) over *http* and make sure
* that all the resources get upgraded to use >> https << when the
* csp-directive "upgrade-insecure-requests" is specified. We further
* test that subresources within nested contexts (iframes) get upgraded
* and also test the handling of server side redirects.
*
* In detail:
* We perform an XHR request to the *.sjs file which is processed async on
* the server and waits till all the requests were processed by the server.
* Once the server received all the different requests, the server responds
* to the initial XHR request with an array of results which must match
* the expected results from each test, making sure that all requests
* received by the server (*.sjs) were actually *https* requests.
*/
const { AppConstants } = SpecialPowers.ChromeUtils.importESModule(
"resource://gre/modules/AppConstants.sys.mjs"
);
const UPGRADE_POLICY =
"upgrade-insecure-requests;" + // upgrade all http requests to https
"block-all-mixed-content;" + // upgrade should be enforced before block-all.
"default-src https: wss: 'unsafe-inline';" + // only allow https: and wss:
"form-action https:;"; // explicit, no fallback to default-src
const UPGRADE_POLICY_NO_DEFAULT_SRC =
"upgrade-insecure-requests;" + // upgrade all http requests to https
"script-src 'unsafe-inline' *"; // we have to allowlist the inline scripts
// in the test.
const NO_UPGRADE_POLICY =
"default-src http: ws: 'unsafe-inline';" + // allow http:// and ws://
"form-action http:;"; // explicit, no fallback to default-src
var tests = [
{ // (1) test that all requests within an >> https << page get updated
policy: UPGRADE_POLICY,
topLevelScheme: "https://",
description: "upgrade all requests on toplevel https",
deliveryMethod: "header",
results: [
"iframe-ok", "script-ok", "img-ok", "img-redir-ok", "font-ok", "xhr-ok", "style-ok",
"media-ok", "object-ok", "form-ok", "nested-img-ok"
]
},
{ // (2) test that all requests within an >> http << page get updated
policy: UPGRADE_POLICY,
topLevelScheme: "http://",
description: "upgrade all requests on toplevel http",
deliveryMethod: "header",
results: [
"iframe-ok", "script-ok", "img-ok", "img-redir-ok", "font-ok", "xhr-ok", "style-ok",
"media-ok", "object-ok", "form-ok", "nested-img-ok"
]
},
{ // (3) test that all requests within an >> http << page get updated, but do
// not specify a default-src directive.
policy: UPGRADE_POLICY_NO_DEFAULT_SRC,
topLevelScheme: "http://",
description: "upgrade all requests on toplevel http where default-src is not specified",
deliveryMethod: "header",
results: [
"iframe-ok", "script-ok", "img-ok", "img-redir-ok", "font-ok", "xhr-ok", "style-ok",
"media-ok", "object-ok", "form-ok", "nested-img-ok"
]
},
{ // (4) test that no requests get updated if >> upgrade-insecure-requests << is not used
policy: NO_UPGRADE_POLICY,
topLevelScheme: "http://",
description: "do not upgrade any requests on toplevel http",
deliveryMethod: "header",
results: [
"iframe-error", "script-error", "img-error", "img-redir-error", "font-error",
"xhr-error", "style-error", "media-error", "object-error", "form-error",
"nested-img-error"
]
},
{ // (5) test that all requests within an >> https << page using meta CSP get updated
// policy: UPGRADE_POLICY, that test uses UPGRADE_POLICY within
// file_upgrade_insecure_meta.html
// no need to define it within that object.
topLevelScheme: "https://",
description: "upgrade all requests on toplevel https using meta csp",
deliveryMethod: "meta",
results: [
"iframe-ok", "script-ok", "img-ok", "img-redir-ok", "font-ok", "xhr-ok", "style-ok",
"media-ok", "object-ok", "form-ok", "nested-img-ok"
]
},
];
// TODO: WebSocket tests are not supported on Android Yet. Bug 1566168.
if (AppConstants.platform !== "android") {
for (let test of tests) {
test.results.push(test.results[0] == "iframe-ok" ? "websocket-ok" : "websocket-error");
}
}
var counter = 0;
var curTest;
function loadTestPage() {
curTest = tests[counter++];
var src = curTest.topLevelScheme + "example.com/tests/dom/security/test/csp/file_testserver.sjs?file=";
if (curTest.deliveryMethod === "header") {
// append the file that should be served
src += escape("tests/dom/security/test/csp/file_upgrade_insecure.html");
// append the CSP that should be used to serve the file
src += "&csp=" + escape(curTest.policy);
}
else {
src += escape("tests/dom/security/test/csp/file_upgrade_insecure_meta.html");
// no csp here, since it's in the meta element
}
document.getElementById("testframe").src = src;
}
function finishTest() {
window.removeEventListener("message", receiveMessage);
SimpleTest.finish();
}
function checkResults(result) {
// try to find the expected result within the results array
var index = curTest.results.indexOf(result);
isnot(index, -1, curTest.description + " (result: " + result + ")");
// take the element out the array and continue till the results array is empty
if (index != -1) {
curTest.results.splice(index, 1);
}
// lets check if we are expecting more results to bubble up
if (curTest.results.length) {
return;
}
// lets see if we ran all the tests
if (counter == tests.length) {
finishTest();
return;
}
// otherwise it's time to run the next test
runNextTest();
}
// a postMessage handler that is used by sandboxed iframes without
// 'allow-same-origin' to bubble up results back to this main page.
window.addEventListener("message", receiveMessage);
function receiveMessage(event) {
checkResults(event.data.result);
}
function runNextTest() {
// sends an xhr request to the server which is processed async, which only
// returns after the server has received all the expected requests.
var myXHR = new XMLHttpRequest();
myXHR.open("GET", "file_upgrade_insecure_server.sjs?queryresult");
myXHR.onload = function(e) {
var results = myXHR.responseText.split(",");
for (var index in results) {
checkResults(results[index]);
}
}
myXHR.onerror = function(e) {
ok(false, "could not query results from server (" + e.message + ")");
finishTest();
}
myXHR.send();
// give it some time and run the testpage
SimpleTest.executeSoon(loadTestPage);
}
SimpleTest.waitForExplicitFinish();
runNextTest();
</script>
</body>
</html>
|