<!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 type="text/javascript" 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 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 whitelist 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", "websocket-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", "websocket-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", "websocket-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", "websocket-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", "websocket-ok", "nested-img-ok" ] }, ]; 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, false); 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 > 0) { 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, false); 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>