<!
DOCTYPE HTML>
<
html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=671389
Bug 671389 - Implement CSP sandbox directive
-->
<
head>
<
meta charset=
"utf-8">
<
title>Tests for Bug 671389</
title>
<
script src=
"/tests/SimpleTest/SimpleTest.js"></
script>
<
link rel=
"stylesheet" type=
"text/css" href=
"/tests/SimpleTest/test.css"/>
</
head>
<
script type=
"application/javascript">
SimpleTest.waitForExplicitFinish();
// Check if two sandbox flags are the same, ignoring case-sensitivity.
// getSandboxFlags returns a list of sandbox flags (if any) or
// null if the flag is not set.
// This function checks if two flags are the same, i.e., they
're
// either not set or have the same flags.
function eqFlags(a, b) {
if (a === null && b === null) { return true; }
if (a === null || b === null) { return false; }
if (a.length !== b.length) { return false; }
var a_sorted = a.
map(function(e) { return e.toLowerCase(); }).sort();
var b_sorted = b.
map(function(e) { return e.toLowerCase(); }).sort();
for (
var i in a_sorted) {
if (a_sorted[i] !== b_sorted[i]) {
return false;
}
}
return true;
}
// Get the sandbox flags of document doc.
// If the flag is not set sandboxFlagsAsString returns null,
// this function also returns null.
// If the flag is set it may have some flags; in this case
// this function returns the (potentially empty) list of flags.
function getSandboxFlags(doc) {
var flags = doc.sandboxFlagsAsString;
if (flags === null) { return null; }
return flags? flags.split(
" "):[];
}
// Constructor for a CSP sandbox flags test. The constructor
// expectes a description
'desc' and set of options
'opts':
// - sandboxAttribute: [null] or string corresponding to the
iframe sandbox attributes
// - csp: [null] or string corresponding to the CSP sandbox flags
// - cspReportOnly: [null] or string corresponding to the CSP report-only sandbox flags
// - file: [null] or string corresponding to file the server should serve
// Above, we use [brackets] to denote default values.
function CSPFlagsTest(desc, opts) {
function ifundef(x, v) {
return (x !== undefined) ? x : v;
}
function intersect(as, bs) { // Intersect two csp attributes:
as = as === null ? null
: as.split(
' ').filter(function(x) { return !!x; });
bs = bs === null ? null
: bs.split(
' ').filter(function(x) { return !!x; });
if (as === null) { return bs; }
if (bs === null) { return as; }
var cs = [];
as.forEach(function(a) {
if (a && bs.includes(a))
cs.push(a);
});
return cs;
}
this.desc = desc ||
"Untitled test";
this.attr = ifundef(opts.sandboxAttribute, null);
this.csp = ifundef(opts.csp, null);
this.cspRO = ifundef(opts.cspReportOnly, null);
this.file = ifundef(opts.file, null);
this.expected = intersect(this.attr, this.csp);
}
// Return function that checks that the actual flags are the same as the
// expected flags
CSPFlagsTest.prototype.checkFlags = function(
iframe) {
var this_ = this;
return function() {
try {
var actual = getSandboxFlags(SpecialPowers.wrap(
iframe).contentDocument);
ok(eqFlags(actual, this_.expected),
this_.desc +
' - expected: "' + this_.expected +
'", got: "' + actual +
'"');
} catch (e) {
ok(false,
this_.desc +
' - expected: "' + this_.expected +
'", failed with: "' + e +
'"');
}
runNextTest();
};
};
// Set the
iframe src and sandbox attribute
CSPFlagsTest.prototype.runTest = function () {
var iframe = document.createElement(
'iframe');
document.getElementById(
"content").appendChild(
iframe);
iframe.onload = this.checkFlags(
iframe);
// set sandbox attribute
if (this.attr === null) {
iframe.removeAttribute(
'sandbox');
} else {
iframe.sandbox = this.attr;
}
// set query string
var src =
'http://mochi.test:8888/tests/dom/security/test/csp/file_testserver.sjs';
var delim =
'?';
if (this.csp !== null) {
src += delim +
'csp=' + escape(
'sandbox ' + this.csp);
delim =
'&';
}
if (this.cspRO !== null) {
src += delim +
'cspRO=' + escape(
'sandbox ' + this.cspRO);
delim =
'&';
}
if (this.file !== null) {
src += delim +
'file=' + escape(this.file);
delim =
'&';
}
iframe.src = src;
iframe.width =
iframe.height = 10;
}
testCases = [
{
desc:
"Test 1: Header should not override attribute",
sandboxAttribute:
"",
csp:
"allow-forms aLLOw-POinter-lock alLOW-popups aLLOW-SAME-ORIGin ALLOW-SCRIPTS allow-top-navigation"
},
{
desc:
"Test 2: Attribute should not override header",
sandboxAttribute:
"sandbox allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation",
csp:
""
},
{
desc:
"Test 3: Header and attribute intersect",
sandboxAttribute:
"allow-same-origin allow-scripts",
csp:
"allow-forms allow-same-origin allow-scripts"
},
{
desc:
"Test 4: CSP sandbox sets the right flags (pt 1)",
csp:
"alLOW-FORms ALLOW-pointer-lock allow-popups allow-same-origin allow-scripts ALLOW-TOP-NAVIGation"
},
{
desc:
"Test 5: CSP sandbox sets the right flags (pt 2)",
csp:
"allow-same-origin allow-TOP-navigation"
},
{
desc:
"Test 6: CSP sandbox sets the right flags (pt 3)",
csp:
"allow-FORMS ALLOW-scripts"
},
{
desc:
"Test 7: CSP sandbox sets the right flags (pt 4)",
csp:
""
},
{
desc:
"Test 8: CSP sandbox sets the right flags (pt 5)",
csp: null
},
{
desc:
"Test 9: Read-only header should not override attribute",
sandboxAttribute:
"",
cspReportOnly:
"allow-forms ALLOW-pointer-lock allow-POPUPS allow-same-origin ALLOW-scripts allow-top-NAVIGATION"
},
{
desc:
"Test 10: Read-only header should not override CSP header",
csp:
"allow-forms allow-scripts",
cspReportOnly:
"allow-forms aLlOw-PoInTeR-lOcK aLLow-pOPupS aLLoW-SaME-oRIgIN alLow-scripts allow-tOp-navigation"
},
{
desc:
"Test 11: Read-only header should not override attribute or CSP header",
sandboxAttribute:
"allow-same-origin allow-scripts",
csp:
"allow-forms allow-same-origin allow-scripts",
cspReportOnly:
"allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation"
},
{
desc:
"Test 12: CSP sandbox not affected by document.write()",
csp:
"allow-scripts",
file:
'tests/dom/security/test/csp/file_iframe_sandbox_document_write.html'
},
].
map(function(t) { return (new CSPFlagsTest(t.desc,t)); });
var testCaseIndex = 0;
//
Track ok messages from iframes
var childMessages = 0;
var totalChildMessages = 1;
// Check to see if we ran all the tests and received all messges
// from child iframes. If so, finish.
function tryFinish() {
if (testCaseIndex === testCases.length && childMessages === totalChildMessages){
SimpleTest.finish();
}
}
function runNextTest() {
tryFinish();
if (testCaseIndex < testCases.length) {
testCases[testCaseIndex].runTest();
testCaseIndex++;
}
}
function receiveMessage(event) {
ok(event.data.ok, event.data.desc);
childMessages++;
tryFinish();
}
window.addEventListener(
"message", receiveMessage);
addLoadEvent(runNextTest);
</
script>
<
body>
<a target=
"_blank" href=
"https://bugzilla.mozilla.org/show_bug.cgi?id=671389">Mozill
a Bug 671389</a> - Implement CSP sandbox directive
<p id="display"></p>
<div id="content">
</div>
</body>
</html>