зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1073952: tests for iframe sandbox srcdoc and data URIs with CSP r=ckerschb,Tomcat
MozReview-Commit-ID: 5Q8XIJPrRPk --HG-- extra : rebase_source : 391431d3585173d096ab58747a854542dfd3adca
This commit is contained in:
Родитель
390a075c26
Коммит
56207a1b8b
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Bug 1073952 - CSP should restrict scripts in srcdoc iframe even if sandboxed</title>
|
||||
</head>
|
||||
<body>
|
||||
<iframe srcdoc="<img src=x onerror='parent.postMessage({result: `unexpected-csp-violation`}, `*`);'>"
|
||||
sandbox="allow-scripts"></iframe>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
content-security-policy: default-src *;
|
|
@ -0,0 +1,79 @@
|
|||
// Custom *.sjs file specifically for the needs of
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1073952
|
||||
|
||||
"use strict";
|
||||
Components.utils.importGlobalProperties(["URLSearchParams"]);
|
||||
|
||||
const SCRIPT = `
|
||||
<script>
|
||||
parent.parent.postMessage({result: "allowed"}, "*");
|
||||
</script>`;
|
||||
|
||||
const SIMPLE_IFRAME_SRCDOC = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><meta charset="utf-8"></head>
|
||||
<body>
|
||||
<iframe sandbox="allow-scripts" srcdoc="` + SCRIPT + `"></iframe>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
const INNER_SRCDOC_IFRAME = `
|
||||
<iframe sandbox='allow-scripts' srcdoc='<script>
|
||||
parent.parent.parent.postMessage({result: "allowed"}, "*");
|
||||
</script>'>
|
||||
</iframe>`;
|
||||
|
||||
const NESTED_IFRAME_SRCDOC = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><meta charset="utf-8"></head>
|
||||
<body>
|
||||
<iframe sandbox="allow-scripts" srcdoc="` + INNER_SRCDOC_IFRAME + `"></iframe>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
|
||||
const INNER_DATAURI_IFRAME = `
|
||||
<iframe sandbox='allow-scripts' src='data:text/html,<script>
|
||||
parent.parent.parent.postMessage({result: "allowed"}, "*");
|
||||
</script>'>
|
||||
</iframe>`;
|
||||
|
||||
const NESTED_IFRAME_SRCDOC_DATAURI = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><meta charset="utf-8"></head>
|
||||
<body>
|
||||
<iframe sandbox="allow-scripts" srcdoc="` + INNER_DATAURI_IFRAME + `"></iframe>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
function handleRequest(request, response) {
|
||||
const query = new URLSearchParams(request.queryString);
|
||||
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
if (typeof query.get("csp") === "string") {
|
||||
response.setHeader("Content-Security-Policy", query.get("csp"), false);
|
||||
}
|
||||
response.setHeader("Content-Type", "text/html", false);
|
||||
|
||||
if (query.get("action") === "simple_iframe_srcdoc") {
|
||||
response.write(SIMPLE_IFRAME_SRCDOC);
|
||||
return;
|
||||
}
|
||||
|
||||
if (query.get("action") === "nested_iframe_srcdoc") {
|
||||
response.write(NESTED_IFRAME_SRCDOC);
|
||||
return;
|
||||
}
|
||||
|
||||
if (query.get("action") === "nested_iframe_srcdoc_datauri") {
|
||||
response.write(NESTED_IFRAME_SRCDOC_DATAURI);
|
||||
return;
|
||||
}
|
||||
|
||||
// we should never get here, but just in case
|
||||
// return something unexpected
|
||||
response.write("do'h");
|
||||
}
|
|
@ -205,6 +205,9 @@ support-files =
|
|||
file_upgrade_insecure_navigation.sjs
|
||||
file_punycode_host_src.sjs
|
||||
file_punycode_host_src.js
|
||||
file_iframe_srcdoc.sjs
|
||||
file_iframe_sandbox_srcdoc.html
|
||||
file_iframe_sandbox_srcdoc.html^headers^
|
||||
|
||||
[test_base-uri.html]
|
||||
[test_blob_data_schemes.html]
|
||||
|
@ -293,3 +296,5 @@ tags = mcb
|
|||
[test_strict_dynamic_default_src.html]
|
||||
[test_upgrade_insecure_navigation.html]
|
||||
[test_punycode_host_src.html]
|
||||
[test_iframe_sandbox_srcdoc.html]
|
||||
[test_iframe_srcdoc.html]
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Bug 1073952 - CSP should restrict scripts in srcdoc iframe even if sandboxed</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display">Bug 1073952</p>
|
||||
<iframe style="width:200px;height:200px;" id='cspframe'></iframe>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
// This is used to watch the blocked data bounce off CSP and allowed data
|
||||
// get sent out to the wire.
|
||||
function examiner() {
|
||||
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
|
||||
}
|
||||
|
||||
examiner.prototype = {
|
||||
observe: function(subject, topic, data) {
|
||||
|
||||
if(topic === "csp-on-violate-policy") {
|
||||
var violationString = SpecialPowers.getPrivilegedProps(SpecialPowers.
|
||||
do_QueryInterface(subject, "nsISupportsCString"), "data");
|
||||
// the violation subject for inline script violations is unfortunately vague,
|
||||
// all we can do is match the string.
|
||||
if (!violationString.includes("Inline Script")) {
|
||||
return
|
||||
}
|
||||
ok(true, "CSP inherited into sandboxed srcdoc iframe, script blocked.");
|
||||
window.testFinished();
|
||||
}
|
||||
},
|
||||
|
||||
// must eventually call this to remove the listener,
|
||||
// or mochitests might get borked.
|
||||
remove: function() {
|
||||
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
|
||||
}
|
||||
}
|
||||
|
||||
window.examiner = new examiner();
|
||||
|
||||
function testFinished() {
|
||||
window.examiner.remove();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
addEventListener("message", function(e) {
|
||||
ok(false, "We should not execute JS in srcdoc iframe.");
|
||||
window.testFinished();
|
||||
})
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// save this for last so that our listeners are registered.
|
||||
// ... this loads the testbed of good and bad requests.
|
||||
document.getElementById('cspframe').src = 'file_iframe_sandbox_srcdoc.html';
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,140 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1073952 - Test CSP enforcement within iframe srcdoc</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:
|
||||
* (1) We serve a site which makes use of script-allowed sandboxed iframe srcdoc
|
||||
* and make sure that CSP applies to the nested browsing context
|
||||
* within the iframe.
|
||||
* [PAGE WITH CSP [IFRAME SANDBOX SRCDOC [SCRIPT]]]
|
||||
*
|
||||
* (2) We serve a site which nests script within an script-allowed sandboxed
|
||||
* iframe srcdoc within another script-allowed sandboxed iframe srcdoc and
|
||||
* make sure that CSP applies to the nested browsing context
|
||||
* within the iframe*s*.
|
||||
* [PAGE WITH CSP [IFRAME SANDBOX SRCDOC [IFRAME SANDBOX SRCDOC [SCRIPT]]]]
|
||||
*
|
||||
* Please note that the test relies on the "csp-on-violate-policy" observer.
|
||||
* Whenever the script within the iframe is blocked observers are notified.
|
||||
* In turn, this renders the 'result' within tests[] unused. In case the script
|
||||
* would execute however, the postMessageHandler would bubble up 'allowed' and
|
||||
* the test would fail.
|
||||
*/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var tests = [
|
||||
// [PAGE *WITHOUT* CSP [IFRAME SRCDOC [SCRIPT]]]
|
||||
{ csp: "",
|
||||
result: "allowed",
|
||||
query: "simple_iframe_srcdoc",
|
||||
desc: "No CSP should run script within script-allowed sandboxed iframe srcdoc"
|
||||
},
|
||||
{ csp: "script-src https://test1.com",
|
||||
result: "blocked",
|
||||
query: "simple_iframe_srcdoc",
|
||||
desc: "CSP should block script within script-allowed sandboxediframe srcdoc"
|
||||
},
|
||||
// [PAGE *WITHOUT* CSP [IFRAME SRCDOC [IFRAME SRCDOC [SCRIPT]]]]
|
||||
{ csp: "",
|
||||
result: "allowed",
|
||||
query: "nested_iframe_srcdoc",
|
||||
desc: "No CSP should run script within script-allowed sandboxed iframe srcdoc nested within another script-allowed sandboxed iframe srcdoc"
|
||||
},
|
||||
// [PAGE WITH CSP [IFRAME SRCDOC ]]
|
||||
{ csp: "script-src https://test2.com",
|
||||
result: "blocked",
|
||||
query: "nested_iframe_srcdoc",
|
||||
desc: "CSP should block script within script-allowed sandboxed iframe srcdoc nested within another script-allowed sandboxed iframe srcdoc"
|
||||
},
|
||||
{ csp: "",
|
||||
result: "allowed",
|
||||
query: "nested_iframe_srcdoc_datauri",
|
||||
desc: "No CSP, should run script within script-allowed sandboxed iframe src with data URL nested within another script-allowed sandboxed iframe srcdoc"
|
||||
},
|
||||
{ csp: "script-src https://test3.com",
|
||||
result: "blocked",
|
||||
query: "nested_iframe_srcdoc_datauri",
|
||||
desc: "CSP should block script within script-allowed sandboxed iframe src with data URL nested within another script-allowed sandboxed iframe srcdoc"
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
// initializing to -1 so we start at index 0 when we start the test
|
||||
var counter = -1;
|
||||
|
||||
function finishTest() {
|
||||
window.removeEventListener("message", receiveMessage, false);
|
||||
window.examiner.remove();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.addEventListener("message", receiveMessage, false);
|
||||
function receiveMessage(event) {
|
||||
var result = event.data.result;
|
||||
testComplete(result, tests[counter].result, tests[counter].desc);
|
||||
}
|
||||
|
||||
function examiner() {
|
||||
SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
|
||||
}
|
||||
|
||||
examiner.prototype = {
|
||||
observe: function(subject, topic, data) {
|
||||
if (topic === "csp-on-violate-policy") {
|
||||
var violationString = SpecialPowers.getPrivilegedProps(SpecialPowers.
|
||||
do_QueryInterface(subject, "nsISupportsCString"), "data");
|
||||
// the violation subject for inline script violations is unfortunately vague,
|
||||
// all we can do is match the string.
|
||||
if (!violationString.includes("Inline Script")) {
|
||||
return
|
||||
}
|
||||
testComplete("blocked", tests[counter].result, tests[counter].desc);
|
||||
}
|
||||
},
|
||||
remove: function() {
|
||||
SpecialPowers.removeObserver(this, "csp-on-violate-policy");
|
||||
}
|
||||
}
|
||||
|
||||
function testComplete(result, expected, desc) {
|
||||
is(result, expected, desc);
|
||||
// ignore cases when we get csp violations and postMessage from the same frame.
|
||||
var frameURL = new URL(document.getElementById("testframe").src);
|
||||
var params = new URLSearchParams(frameURL.search);
|
||||
var counterInFrame = params.get("counter");
|
||||
if (counterInFrame == counter) {
|
||||
loadNextTest();
|
||||
}
|
||||
}
|
||||
|
||||
function loadNextTest() {
|
||||
counter++;
|
||||
if (counter == tests.length) {
|
||||
finishTest();
|
||||
return;
|
||||
}
|
||||
var src = "file_iframe_srcdoc.sjs";
|
||||
src += "?csp=" + escape(tests[counter].csp);
|
||||
src += "&action=" + escape(tests[counter].query);
|
||||
src += "&counter=" + counter;
|
||||
document.getElementById("testframe").src = src;
|
||||
}
|
||||
|
||||
// start running the tests
|
||||
window.examiner = new examiner();
|
||||
loadNextTest();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче