mirror of
https://github.com/servo/servo.git
synced 2025-09-17 02:18:23 +01:00
Update web-platform-tests to revision a46616a5b18e83587ddbbed756c7b96cbb4b015d
This commit is contained in:
parent
3f07cfec7c
commit
578498ba24
4001 changed files with 159517 additions and 30260 deletions
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Security-Policy" content="base-uri {{location[scheme]}}://{{domains[www1]}}:{{ports[http][0]}}/">
|
||||
<script src='/resources/testharness.js'></script>
|
||||
<script src='/resources/testharnessreport.js'></script>
|
||||
|
||||
<script>
|
||||
var t = async_test("Check that base URIs can be set if they do not violate the page's policy.");
|
||||
window.addEventListener('securitypolicyviolation', t.step_func(function(t) {
|
||||
assert_unreached('No CSP violation report should have been fired.');
|
||||
}));
|
||||
</script>
|
||||
|
||||
<base href="{{location[scheme]}}://{{domains[www1]}}:{{ports[http][0]}}/">
|
||||
<script>
|
||||
t.step(function() {
|
||||
assert_equals(document.baseURI, "{{location[scheme]}}://{{domains[www1]}}:{{ports[http][0]}}/");
|
||||
t.done();
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</html>
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Security-Policy" content="base-uri {{location[scheme]}}://{{domains[www1]}}:{{ports[http][0]}}/">
|
||||
<script src='/resources/testharness.js'></script>
|
||||
<script src='/resources/testharnessreport.js'></script>
|
||||
|
||||
<script>
|
||||
var t = async_test("Check that baseURI fires a securitypolicyviolation event when it does not match the csp directive");
|
||||
window.addEventListener('securitypolicyviolation', t.step_func_done(function(e) {
|
||||
assert_equals(e.blockedURI, "{{location[scheme]}}://{{domains[www2]}}:{{ports[http][0]}}/")
|
||||
assert_equals(e.violatedDirective, "base-uri");
|
||||
}));
|
||||
</script>
|
||||
|
||||
<base href="{{location[scheme]}}://{{domains[www2]}}:{{ports[http][0]}}/">
|
||||
<script>
|
||||
test(function() {
|
||||
assert_equals(document.baseURI, window.location.href);
|
||||
t.done();
|
||||
}, "Check that the baseURI is not set when it does not match the csp directive");
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</html>
|
|
@ -2,12 +2,11 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="base-uri {{location[scheme]}}://{{domains[]}}:{{ports[http][0]}}/base/">
|
||||
|
||||
<title>base-uri works correctly inside a sandboxed iframe.</title>
|
||||
<script src='/resources/testharness.js'></script>
|
||||
<script src='/resources/testharnessreport.js'></script>
|
||||
|
||||
<!-- CSP served: base-uri 'self' -->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@ -16,7 +15,7 @@
|
|||
|
||||
<script>
|
||||
window.addEventListener('securitypolicyviolation', function(e) {
|
||||
assert_unreached('No CSP violation report has fired.');
|
||||
assert_unreached('No CSP violation report should have been fired.');
|
||||
});
|
||||
|
||||
async_test(function(t) {
|
||||
|
@ -24,21 +23,21 @@
|
|||
i.sandbox = 'allow-scripts';
|
||||
i.style.display = 'none';
|
||||
i.srcdoc = `
|
||||
<script>
|
||||
window.addEventListener('securitypolicyviolation', function() {
|
||||
top.postMessage('FAIL', '*');
|
||||
});
|
||||
</sc` + `ript>
|
||||
<base href="{{location[scheme]}}://{{domains[]}}:{{ports[http][0]}}/base/">
|
||||
<script>
|
||||
top.postMessage(document.baseURI, '*');
|
||||
</sc` + `ript>`;
|
||||
<script>
|
||||
window.addEventListener('securitypolicyviolation', function() {
|
||||
top.postMessage('FAIL', '*');
|
||||
});
|
||||
</sc` + `ript>
|
||||
<base href="{{location[scheme]}}://{{domains[]}}:{{ports[http][0]}}/base/">
|
||||
<script>
|
||||
top.postMessage(document.baseURI, '*');
|
||||
</sc` + `ript>`;
|
||||
|
||||
window.addEventListener('message', t.step_func(function(e) {
|
||||
if (e.source === i.contentWindow) {
|
||||
assert_equals(e.data, location.origin + '/base/');
|
||||
t.done();
|
||||
}
|
||||
if (e.source === i.contentWindow) {
|
||||
assert_equals(e.data, location.origin + '/base/');
|
||||
t.done();
|
||||
}
|
||||
}));
|
||||
|
||||
document.body.appendChild(i);
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
Expires: Mon, 26 Jul 1997 05:00:00 GMT
|
||||
Cache-Control: no-store, no-cache, must-revalidate
|
||||
Cache-Control: post-check=0, pre-check=0, false
|
||||
Pragma: no-cache
|
||||
Content-Security-Policy: base-uri 'self'
|
|
@ -1,70 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Embedded Enforcement: Embedding-CSP header.</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="support/testharness-helper.sub.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
// When this test starts passing please merge with embedding_csp-header.html
|
||||
var tests = [
|
||||
{ "name": "Wrong value of `csp` should not trigger sending Embedding-CSP Header.",
|
||||
"csp": "completely wrong csp",
|
||||
"expected": null},
|
||||
];
|
||||
|
||||
tests.forEach(test => {
|
||||
async_test(t => {
|
||||
var url = generateURLString(Host.SAME_ORIGIN, PolicyHeader.EMBEDDING_CSP);
|
||||
assert_embedding_csp(t, url, test.csp, test.expected);
|
||||
}, "Test same origin: " + test.name);
|
||||
|
||||
async_test(t => {
|
||||
var url = generateURLString(Host.SAME_ORIGIN, PolicyHeader.EMBEDDING_CSP);
|
||||
var redirect_url = generateRedirect(Host.SAME_ORIGIN, url);
|
||||
assert_embedding_csp(t, redirect_url, test.csp, test.expected);
|
||||
}, "Test same origin redirect: " + test.name);
|
||||
|
||||
async_test(t => {
|
||||
var url = generateURLString(Host.SAME_ORIGIN, PolicyHeader.EMBEDDING_CSP);
|
||||
var redirect_url = generateRedirect(Host.CROSS_ORIGIN, url);
|
||||
assert_embedding_csp(t, redirect_url, test.csp, test.expected);
|
||||
}, "Test cross origin redirect: " + test.name);
|
||||
|
||||
async_test(t => {
|
||||
var url = generateURLString(Host.CROSS_ORIGIN, PolicyHeader.EMBEDDING_CSP);
|
||||
var redirect_url = generateRedirect(Host.CROSS_ORIGIN, url);
|
||||
assert_embedding_csp(t, redirect_url, test.csp, test.expected);
|
||||
}, "Test cross origin redirect of cross origin iframe: " + test.name);
|
||||
|
||||
async_test(t => {
|
||||
var i = document.createElement('iframe');
|
||||
if (test.csp)
|
||||
i.csp = test.csp;
|
||||
i.src = generateURLString(Host.SAME_ORIGIN, PolicyHeader.EMBEDDING_CSP);
|
||||
var loaded = false;
|
||||
|
||||
window.addEventListener('message', t.step_func(e => {
|
||||
if (e.source != i.contentWindow || !('embedding_csp' in e.data))
|
||||
return;
|
||||
if (!loaded) {
|
||||
assert_equals(test.expected, e.data['embedding_csp']);
|
||||
loaded = true;
|
||||
i.csp = "default-src 'unsafe-inline'";
|
||||
i.src = generateURLString(Host.CROSS_ORIGIN, PolicyHeader.EMBEDDING_CSP);
|
||||
} else {
|
||||
// Once iframe has loaded, check that on change of `src` attribute
|
||||
// Embedding-CSP value is based on latest `csp` attribute value.
|
||||
assert_equals("default-src 'unsafe-inline'", e.data['embedding_csp']);
|
||||
t.done();
|
||||
}
|
||||
}));
|
||||
|
||||
document.body.appendChild(i);
|
||||
}, "Test Embedding-CSP value on `csp` change: " + test.name);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,75 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Embedded Enforcement: Embedding-CSP header.</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="support/testharness-helper.sub.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
var tests = [
|
||||
{ "name": "Embedding-CSP is not sent if `csp` attribute is not set on <iframe>.",
|
||||
"csp": null,
|
||||
"expected": null },
|
||||
{ "name": "Send Embedding-CSP when `csp` attribute of <iframe> is not empty.",
|
||||
"csp": "script-src 'unsafe-inline'",
|
||||
"expected": "script-src 'unsafe-inline'" },
|
||||
{ "name": "Send Embedding-CSP Header on change of `src` attribute on iframe.",
|
||||
"csp": "script-src 'unsafe-inline'",
|
||||
"expected": "script-src 'unsafe-inline'" },
|
||||
];
|
||||
|
||||
tests.forEach(test => {
|
||||
async_test(t => {
|
||||
var url = generateURLString(Host.SAME_ORIGIN, PolicyHeader.EMBEDDING_CSP);
|
||||
assert_embedding_csp(t, url, test.csp, test.expected);
|
||||
}, "Test same origin: " + test.name);
|
||||
|
||||
async_test(t => {
|
||||
var url = generateURLString(Host.SAME_ORIGIN, PolicyHeader.EMBEDDING_CSP);
|
||||
var redirect_url = generateRedirect(Host.SAME_ORIGIN, url);
|
||||
assert_embedding_csp(t, redirect_url, test.csp, test.expected);
|
||||
}, "Test same origin redirect: " + test.name);
|
||||
|
||||
async_test(t => {
|
||||
var url = generateURLString(Host.SAME_ORIGIN, PolicyHeader.EMBEDDING_CSP);
|
||||
var redirect_url = generateRedirect(Host.CROSS_ORIGIN, url);
|
||||
assert_embedding_csp(t, redirect_url, test.csp, test.expected);
|
||||
}, "Test cross origin redirect: " + test.name);
|
||||
|
||||
async_test(t => {
|
||||
var url = generateURLString(Host.CROSS_ORIGIN, PolicyHeader.EMBEDDING_CSP);
|
||||
var redirect_url = generateRedirect(Host.CROSS_ORIGIN, url);
|
||||
assert_embedding_csp(t, redirect_url, test.csp, test.expected);
|
||||
}, "Test cross origin redirect of cross origin iframe: " + test.name);
|
||||
|
||||
async_test(t => {
|
||||
var i = document.createElement('iframe');
|
||||
if (test.csp)
|
||||
i.csp = test.csp;
|
||||
i.src = generateURLString(Host.SAME_ORIGIN, PolicyHeader.EMBEDDING_CSP);
|
||||
var loaded = false;
|
||||
|
||||
window.addEventListener('message', t.step_func(e => {
|
||||
if (e.source != i.contentWindow || !('embedding_csp' in e.data))
|
||||
return;
|
||||
if (!loaded) {
|
||||
assert_equals(test.expected, e.data['embedding_csp']);
|
||||
loaded = true;
|
||||
i.csp = "default-src 'unsafe-inline'";
|
||||
i.src = generateURLString(Host.CROSS_ORIGIN, PolicyHeader.EMBEDDING_CSP);
|
||||
} else {
|
||||
// Once iframe has loaded, check that on change of `src` attribute
|
||||
// Embedding-CSP value is based on latest `csp` attribute value.
|
||||
assert_equals("default-src 'unsafe-inline'", e.data['embedding_csp']);
|
||||
t.done();
|
||||
}
|
||||
}));
|
||||
|
||||
document.body.appendChild(i);
|
||||
}, "Test Embedding-CSP value on `csp` change: " + test.name);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,108 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Embedded Enforcement: Sec-Required-CSP header.</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="support/testharness-helper.sub.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
var tests = [
|
||||
{ "name": "Sec-Required-CSP is not sent if `csp` attribute is not set on <iframe>.",
|
||||
"csp": null,
|
||||
"expected": null },
|
||||
{ "name": "Send Sec-Required-CSP when `csp` attribute of <iframe> is not empty.",
|
||||
"csp": "script-src 'unsafe-inline'",
|
||||
"expected": "script-src 'unsafe-inline'" },
|
||||
{ "name": "Send Sec-Required-CSP Header on change of `src` attribute on iframe.",
|
||||
"csp": "script-src 'unsafe-inline'",
|
||||
"expected": "script-src 'unsafe-inline'" },
|
||||
{ "name": "Wrong value of `csp` should not trigger sending Sec-Required-CSP Header - gibberish csp",
|
||||
"csp": "completely wrong csp",
|
||||
"expected": null },
|
||||
{ "name": "Wrong value of `csp` should not trigger sending Sec-Required-CSP Header - unknown policy name",
|
||||
"csp": "invalid-policy-name http://example.com",
|
||||
"expected": null },
|
||||
{ "name": "Wrong value of `csp` should not trigger sending Sec-Required-CSP Header - unknown policy name in multiple directives",
|
||||
"csp": "default-src http://example.com; invalid-policy-name http://example.com",
|
||||
"expected": null },
|
||||
{ "name": "Wrong value of `csp` should not trigger sending Sec-Required-CSP Header - misspeled 'none'",
|
||||
"csp": "default-src 'non'",
|
||||
"expected": null },
|
||||
{ "name": "Wrong value of `csp` should not trigger sending Sec-Required-CSP Header - query values in path",
|
||||
"csp": "script-src 127.0.0.1:8000/path?query=string",
|
||||
"expected": null },
|
||||
{ "name": "Wrong value of `csp` should not trigger sending Sec-Required-CSP Header - missing semicolon",
|
||||
"csp": "script-src 'self' object-src 'self' style-src *",
|
||||
"expected": null },
|
||||
{ "name": "Wrong value of `csp` should not trigger sending Sec-Required-CSP Header - comma separated",
|
||||
"csp": "script-src 'none', object-src 'none'",
|
||||
"expected": null },
|
||||
{ "name": "Wrong value of `csp` should not trigger sending Sec-Required-CSP Header - html encoded string",
|
||||
// script-src 127.0.0.1:8000
|
||||
"csp": "script-src 127.0.0.1:8000",
|
||||
"expected": null },
|
||||
{ "name": "Wrong value of `csp` should not trigger sending Sec-Required-CSP Header - url encoded string",
|
||||
// script-src 127.0.0.1:8000
|
||||
"csp": "script-src%20127.0.0.1%3A8000",
|
||||
"expected": null },
|
||||
{ "name": "Wrong value of `csp` should not trigger sending Sec-Required-CSP Header - report-uri present",
|
||||
"csp": "script-src 'unsafe-inline'; report-uri resources/dummy-report.php",
|
||||
"expected": null },
|
||||
// TODO(andypaicu): when `report-to` is implemented, add tests here.
|
||||
];
|
||||
|
||||
tests.forEach(test => {
|
||||
async_test(t => {
|
||||
var url = generateURLString(Host.SAME_ORIGIN, PolicyHeader.REQUIRED_CSP);
|
||||
assert_required_csp(t, url, test.csp, test.expected);
|
||||
}, "Test same origin: " + test.name);
|
||||
|
||||
async_test(t => {
|
||||
var url = generateURLString(Host.SAME_ORIGIN, PolicyHeader.REQUIRED_CSP);
|
||||
var redirect_url = generateRedirect(Host.SAME_ORIGIN, url);
|
||||
assert_required_csp(t, redirect_url, test.csp, test.expected);
|
||||
}, "Test same origin redirect: " + test.name);
|
||||
|
||||
async_test(t => {
|
||||
var url = generateURLString(Host.SAME_ORIGIN, PolicyHeader.REQUIRED_CSP);
|
||||
var redirect_url = generateRedirect(Host.CROSS_ORIGIN, url);
|
||||
assert_required_csp(t, redirect_url, test.csp, test.expected);
|
||||
}, "Test cross origin redirect: " + test.name);
|
||||
|
||||
async_test(t => {
|
||||
var url = generateURLString(Host.CROSS_ORIGIN, PolicyHeader.REQUIRED_CSP);
|
||||
var redirect_url = generateRedirect(Host.CROSS_ORIGIN, url);
|
||||
assert_required_csp(t, redirect_url, test.csp, test.expected);
|
||||
}, "Test cross origin redirect of cross origin iframe: " + test.name);
|
||||
|
||||
async_test(t => {
|
||||
var i = document.createElement('iframe');
|
||||
if (test.csp)
|
||||
i.csp = test.csp;
|
||||
i.src = generateURLString(Host.SAME_ORIGIN, PolicyHeader.REQUIRED_CSP);
|
||||
var loaded = false;
|
||||
|
||||
window.addEventListener('message', t.step_func(e => {
|
||||
if (e.source != i.contentWindow || !('required_csp' in e.data))
|
||||
return;
|
||||
if (!loaded) {
|
||||
assert_equals(e.data['required_csp'], test.expected);
|
||||
loaded = true;
|
||||
i.csp = "default-src 'unsafe-inline'";
|
||||
i.src = generateURLString(Host.CROSS_ORIGIN, PolicyHeader.REQUIRED_CSP);
|
||||
} else {
|
||||
// Once iframe has loaded, check that on change of `src` attribute
|
||||
// Required-CSP value is based on latest `csp` attribute value.
|
||||
assert_equals(e.data['required_csp'], "default-src 'unsafe-inline'");
|
||||
t.done();
|
||||
}
|
||||
}));
|
||||
|
||||
document.body.appendChild(i);
|
||||
}, "Test Required-CSP value on `csp` change: " + test.name);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,59 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Embedded Enforcement: Subsumption Algorithm - Nonces.</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="support/testharness-helper.sub.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
var tests = [
|
||||
{ "name": "Exact nonce subsumes.",
|
||||
"required_csp": "script-src 'nonce-abc'",
|
||||
"returned_csp_1": "script-src 'nonce-abc'",
|
||||
"expected": IframeLoad.EXPECT_LOAD },
|
||||
{ "name": "Any nonce subsumes.",
|
||||
"required_csp": "style-src 'nonce-abc'",
|
||||
"returned_csp_1": "style-src 'nonce-xyz'",
|
||||
"expected": IframeLoad.EXPECT_LOAD },
|
||||
{ "name": "A nonce has to be returned if required by the embedder.",
|
||||
"required_csp": "script-src 'nonce-abc'",
|
||||
"returned_csp_1": "script-src http://example1.com/foo",
|
||||
"expected": IframeLoad.EXPECT_BLOCK },
|
||||
{ "name": "Multiples nonces returned subsume.",
|
||||
"required_csp": "style-src 'nonce-abc'",
|
||||
"returned_csp_1": "style-src 'nonce-xyz' 'nonce-abc'",
|
||||
"expected": IframeLoad.EXPECT_LOAD },
|
||||
// nonce intersection
|
||||
{ "name": "Nonce intersection is still done on exact match - non-matching nonces.",
|
||||
"required_csp": "script-src 'nonce-abc'",
|
||||
"returned_csp_1": "script-src 'nonce-def'",
|
||||
"returned_csp_2": "script-src 'nonce-xyz'",
|
||||
"expected": IframeLoad.EXPECT_BLOCK },
|
||||
{ "name": "Nonce intersection is still done on exact match - matching nonces.",
|
||||
"required_csp": "style-src 'nonce-abc'",
|
||||
"returned_csp_1": "style-src 'nonce-def'",
|
||||
"returned_csp_2": "style-src 'nonce-def' 'nonce-xyz'",
|
||||
"expected": IframeLoad.EXPECT_LOAD },
|
||||
// other expressions still have to work
|
||||
{ "name": "Other expressions still have to be subsumed - positive test.",
|
||||
"required_csp": "style-src http://example1.com/foo/ 'nonce-abc'",
|
||||
"returned_csp_1": "style-src http://example1.com/foo/ 'nonce-xyz'",
|
||||
"expected": IframeLoad.EXPECT_LOAD },
|
||||
{ "name": "Other expressions still have to be subsumed - negative test",
|
||||
"required_csp": "script-src http://example1.com/foo/ 'nonce-abc'",
|
||||
"returned_csp_1": "script-src http://not-example1.com/foo/ 'nonce-xyz'",
|
||||
"expected": IframeLoad.EXPECT_BLOCK },
|
||||
];
|
||||
tests.forEach(test => {
|
||||
async_test(t => {
|
||||
var url = generateUrlWithPolicies(Host.CROSS_ORIGIN, test.returned_csp_1);
|
||||
if (test.returned_csp_2)
|
||||
url.searchParams.append("policy2", test.returned_csp_2);
|
||||
assert_iframe_with_csp(t, url, test.required_csp, test.expected, test.name, null);
|
||||
}, test.name);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,8 +1,8 @@
|
|||
import json
|
||||
def main(request, response):
|
||||
header = request.headers.get("Embedding-CSP");
|
||||
header = request.headers.get("Sec-Required-CSP");
|
||||
message = {}
|
||||
message['embedding_csp'] = header if header else None
|
||||
message['required_csp'] = header if header else None
|
||||
return [("Content-Type", "text/html"), ("Allow-CSP-From", "*")], '''
|
||||
<!DOCTYPE html>
|
||||
<html>
|
|
@ -6,7 +6,7 @@ const Host = {
|
|||
const PolicyHeader = {
|
||||
CSP: "echo-policy.py?policy=",
|
||||
CSP_MULTIPLE: "echo-policy-multiple.py",
|
||||
EMBEDDING_CSP: "echo-embedding-csp.py",
|
||||
REQUIRED_CSP: "echo-required-csp.py",
|
||||
ALLOW_CSP_FROM: "echo-allow-csp-from.py",
|
||||
};
|
||||
|
||||
|
@ -68,16 +68,16 @@ function generateUrlWithAllowCSPFrom(host, allowCspFrom) {
|
|||
return url;
|
||||
}
|
||||
|
||||
function assert_embedding_csp(t, url, csp, expected) {
|
||||
function assert_required_csp(t, url, csp, expected) {
|
||||
var i = document.createElement('iframe');
|
||||
if(csp)
|
||||
i.csp = csp;
|
||||
i.src = url;
|
||||
|
||||
window.addEventListener('message', t.step_func(e => {
|
||||
if (e.source != i.contentWindow || !('embedding_csp' in e.data))
|
||||
return;
|
||||
assert_equals(expected, e.data['embedding_csp']);
|
||||
if (e.source != i.contentWindow || !('required_csp' in e.data))
|
||||
return;
|
||||
assert_equals(e.data['required_csp'], expected);
|
||||
t.done();
|
||||
}));
|
||||
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
<!doctype html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="./support/testharness-helper.sub.js"></script>
|
||||
<body></body>
|
||||
<script>
|
||||
function waitForViolation(el, policy, blocked_origin) {
|
||||
return new Promise(resolve => {
|
||||
el.addEventListener('securitypolicyviolation', e => {
|
||||
if (e.originalPolicy == policy && (new URL(e.blockedURI)).origin == blocked_origin)
|
||||
resolve(e);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async_test(t => {
|
||||
var i = document.createElement("iframe");
|
||||
var redirect = generateCrossOriginRedirectFrame();
|
||||
i.src = redirect.url;
|
||||
|
||||
// Report-only policy should trigger a violation on the original request.
|
||||
var original_report_only = waitForViolation(window, "frame-src http://foo.test", (new URL(i.src)).origin)
|
||||
// Report-only policy should trigger a violation on the redirected request.
|
||||
var redirect_report_only = waitForViolation(window, "frame-src http://foo.test", (new URL(redirect.target)).origin)
|
||||
// Enforced policy should trigger a violation on the redirected request.
|
||||
var redirect_enforced = waitForViolation(window, "frame-src 'self'", (new URL(redirect.target)).origin)
|
||||
|
||||
Promise.all([original_report_only, redirect_report_only, redirect_enforced]).then(t.step_func(_ => {
|
||||
t.done();
|
||||
}));
|
||||
|
||||
document.body.appendChild(i);
|
||||
}, "Redirected iframe src should evaluate both enforced and report-only policies on both original request and when following redirect");
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,2 @@
|
|||
Content-Security-Policy: frame-src 'self'
|
||||
Content-Security-Policy-Report-Only: frame-src http://foo.test
|
|
@ -0,0 +1,49 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>frame-src-self-unique-origin</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>
|
||||
The origin of an URL is called "unique" when it is considered to be
|
||||
different from every origin, including itself. The origin of a
|
||||
data-url is unique. When the current origin is unique, the CSP source
|
||||
'self' must not match any URL.
|
||||
</p>
|
||||
<script>
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.src = encodeURI(`data:text/html,
|
||||
<script>
|
||||
/* Add the CSP: frame-src: 'self'. */
|
||||
var meta = document.createElement('meta');
|
||||
meta.httpEquiv = 'Content-Security-Policy';
|
||||
meta.content = "frame-src 'self'";
|
||||
document.getElementsByTagName('head')[0].appendChild(meta);
|
||||
|
||||
/* Notify the parent the iframe has been blocked. */
|
||||
window.addEventListener('securitypolicyviolation', e => {
|
||||
if (e.originalPolicy == "frame-src 'self'")
|
||||
window.parent.postMessage('Test PASS', '*');
|
||||
});
|
||||
</scr`+`ipt>
|
||||
|
||||
This iframe should be blocked by CSP:
|
||||
<iframe src='data:text/html,blocked_iframe'></iframe>
|
||||
`);
|
||||
if (window.async_test) {
|
||||
async_test(t => {
|
||||
window.addEventListener("message", e => {
|
||||
if (e.data == "Test PASS")
|
||||
t.done();
|
||||
});
|
||||
}, "Iframe's url must not match with 'self'. It must be blocked.");
|
||||
}
|
||||
document.body.appendChild(iframe);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,2 @@
|
|||
<!doctype html>
|
||||
</html>
|
|
@ -0,0 +1,5 @@
|
|||
function generateCrossOriginRedirectFrame() {
|
||||
var target = "http://{{domains[天気の良い日]}}:" + document.location.port + "/content-security-policy/frame-src/support/frame.html";
|
||||
var url = "/common/redirect.py?location=" + encodeURIComponent(target);
|
||||
return { url: url, target: target };
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>img-src-self-unique-origin</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>
|
||||
The origin of an URL is called "unique" when it is considered to be
|
||||
different from every origin, including itself. The origin of a
|
||||
data-url is unique. When the current origin is unique, the CSP source
|
||||
'self' must not match any URL.
|
||||
</p>
|
||||
<script>
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.src = encodeURI(`data:text/html,
|
||||
<script>
|
||||
/* Add the CSP: frame-src: 'self'. */
|
||||
var meta = document.createElement('meta');
|
||||
meta.httpEquiv = 'Content-Security-Policy';
|
||||
meta.content = "img-src 'self'";
|
||||
document.getElementsByTagName('head')[0].appendChild(meta);
|
||||
|
||||
/* Notify the parent the image has been blocked. */
|
||||
window.addEventListener('securitypolicyviolation', e => {
|
||||
if (e.originalPolicy == "img-src 'self'")
|
||||
window.parent.postMessage('Test PASS', '*');
|
||||
});
|
||||
</scr`+`ipt>
|
||||
|
||||
This image should be blocked by CSP:
|
||||
<img src='data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7'></img>
|
||||
`);
|
||||
if (window.async_test) {
|
||||
async_test(t => {
|
||||
window.addEventListener("message", e => {
|
||||
if (e.data == "Test PASS")
|
||||
t.done();
|
||||
});
|
||||
}, "Image's url must not match with 'self'. Image must be blocked.");
|
||||
}
|
||||
document.body.appendChild(iframe);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<meta http-equiv="Content-Security-Policy" content="frame-src 'none'">
|
||||
|
||||
<body>
|
||||
|
||||
<script>
|
||||
var t = async_test("<iframe src='javascript:...'> not blocked by 'frame-src'");
|
||||
|
||||
var i = document.createElement('iframe');
|
||||
i.src = "javascript:window.top.t.done();";
|
||||
|
||||
document.body.appendChild(i);
|
||||
</script>
|
|
@ -0,0 +1,130 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<meta http-equiv="content-security-policy" content="script-src 'nonce-abc'; img-src 'none'">
|
||||
|
||||
<body>
|
||||
<!-- Basics -->
|
||||
<script nonce="abc" id="testScript">
|
||||
document.currentScript.setAttribute('executed', 'yay');
|
||||
</script>
|
||||
|
||||
<script nonce="abc">
|
||||
var script = document.querySelector('#testScript');
|
||||
|
||||
test(t => {
|
||||
// Query Selector
|
||||
assert_equals(document.querySelector('body [nonce]'), script);
|
||||
assert_equals(document.querySelector('body [nonce=""]'), null);
|
||||
assert_equals(document.querySelector('body [nonce=abc]'), script);
|
||||
|
||||
assert_equals(script.getAttribute('nonce'), 'abc');
|
||||
assert_equals(script.nonce, 'abc');
|
||||
}, "Reading 'nonce' content attribute and IDL attribute.");
|
||||
|
||||
// Clone node.
|
||||
test(t => {
|
||||
script.setAttribute('executed', 'boo');
|
||||
var s2 = script.cloneNode();
|
||||
assert_equals(s2.nonce, 'abc', 'IDL attribute');
|
||||
assert_equals(s2.getAttribute('nonce'), 'abc');
|
||||
}, "Cloned node retains nonce.");
|
||||
|
||||
async_test(t => {
|
||||
var s2 = script.cloneNode();
|
||||
document.head.appendChild(s2);
|
||||
assert_equals(s2.nonce, 'abc');
|
||||
assert_equals(s2.getAttribute('nonce'), 'abc');
|
||||
window.addEventListener('load', t.step_func_done(_ => {
|
||||
// The cloned script won't execute, as its 'already started' flag is set.
|
||||
assert_equals(s2.getAttribute('executed'), 'boo');
|
||||
}));
|
||||
}, "Cloned node retains nonce when inserted.");
|
||||
|
||||
// Set the content attribute to 'foo'
|
||||
test(t => {
|
||||
script.setAttribute('nonce', 'foo');
|
||||
assert_equals(script.getAttribute('nonce'), 'foo');
|
||||
assert_equals(script.nonce, 'foo');
|
||||
}, "Writing 'nonce' content attribute.");
|
||||
|
||||
// Set the IDL attribute to 'bar'
|
||||
test(t => {
|
||||
script.nonce = 'bar';
|
||||
assert_equals(script.nonce, 'bar');
|
||||
assert_equals(script.getAttribute('nonce'), 'foo');
|
||||
}, "Writing 'nonce' IDL attribute.");
|
||||
|
||||
// Fragment parser.
|
||||
var documentWriteTest = async_test("Document-written script executes.");
|
||||
document.write(`<script nonce='abc'>
|
||||
documentWriteTest.done();
|
||||
test(t => {
|
||||
var script = document.currentScript;
|
||||
assert_equals(script.getAttribute('nonce'), 'abc');
|
||||
assert_equals(script.nonce, 'abc');
|
||||
}, "Document-written script's nonce value.");
|
||||
</scr` + `ipt>`);
|
||||
|
||||
// Create node.
|
||||
async_test(t => {
|
||||
var s = document.createElement('script');
|
||||
s.innerText = script.innerText;
|
||||
s.nonce = 'abc';
|
||||
document.head.appendChild(s);
|
||||
assert_equals(s.nonce, 'abc');
|
||||
assert_equals(s.getAttribute('nonce'), null);
|
||||
|
||||
window.addEventListener('load', t.step_func_done(_ => {
|
||||
assert_equals(s.getAttribute('executed'), 'yay');
|
||||
}));
|
||||
}, "createElement.nonce.");
|
||||
|
||||
async_test(t => {
|
||||
var s = document.createElement('script');
|
||||
s.innerText = script.innerText;
|
||||
s.nonce = 'zyx';
|
||||
s.setAttribute('nonce', 'abc');
|
||||
assert_equals(s.nonce, 'abc');
|
||||
document.head.appendChild(s);
|
||||
assert_equals(s.nonce, 'abc');
|
||||
assert_equals(s.getAttribute('nonce'), 'abc');
|
||||
|
||||
window.addEventListener('load', t.step_func_done(_ => {
|
||||
assert_equals(s.getAttribute('executed'), 'yay');
|
||||
}));
|
||||
}, "setAttribute('nonce') overwrites '.nonce' upon insertion.");
|
||||
|
||||
// Create node.
|
||||
async_test(t => {
|
||||
var s = document.createElement('script');
|
||||
s.innerText = script.innerText;
|
||||
s.setAttribute('nonce', 'abc');
|
||||
assert_equals(s.getAttribute('nonce'), 'abc', "Pre-insertion content");
|
||||
assert_equals(s.nonce, 'abc', "Pre-insertion IDL");
|
||||
document.head.appendChild(s);
|
||||
assert_equals(s.nonce, 'abc', "Post-insertion IDL");
|
||||
assert_equals(s.getAttribute('nonce'), 'abc', "Post-insertion content");
|
||||
|
||||
window.addEventListener('load', t.step_func_done(_ => {
|
||||
assert_equals(s.getAttribute('executed'), 'yay');
|
||||
}));
|
||||
}, "createElement.setAttribute.");
|
||||
</script>
|
||||
|
||||
<!-- CSS Leakage -->
|
||||
<style>
|
||||
#cssTest { display: block; }
|
||||
#cssTest[nonce=abc] { background: url(/security/resources/abe.png); }
|
||||
</style>
|
||||
<script nonce="abc" id="cssTest">
|
||||
async_test(t => {
|
||||
requestAnimationFrame(t.step_func_done(_ => {
|
||||
var script = document.querySelector('#cssTest');
|
||||
var style = getComputedStyle(script);
|
||||
assert_equals(style['display'], 'block');
|
||||
assert_equals(style['background-image'], "url(\"http://web-platform.test:8001/security/resources/abe.png\")");
|
||||
}));
|
||||
}, "Nonces leak via CSS side-channels.");
|
||||
</script>
|
|
@ -0,0 +1,131 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js" nonce="abc"></script>
|
||||
<script src="/resources/testharnessreport.js" nonce="abc"></script>
|
||||
|
||||
<!-- `Content-Security-Policy: script-src 'nonce-abc'; img-src 'none'` delivered via headers -->
|
||||
|
||||
<body>
|
||||
<!-- Basics -->
|
||||
<script nonce="abc" id="testScript">
|
||||
document.currentScript.setAttribute('executed', 'yay');
|
||||
</script>
|
||||
|
||||
<script nonce="abc">
|
||||
var script = document.querySelector('#testScript');
|
||||
|
||||
test(t => {
|
||||
// Query Selector
|
||||
assert_equals(document.querySelector('body [nonce]'), script);
|
||||
assert_equals(document.querySelector('body [nonce=""]'), script);
|
||||
assert_equals(document.querySelector('body [nonce=abc]'), null);
|
||||
|
||||
assert_equals(script.getAttribute('nonce'), '');
|
||||
assert_equals(script.nonce, 'abc');
|
||||
}, "Reading 'nonce' content attribute and IDL attribute.");
|
||||
|
||||
// Clone node.
|
||||
test(t => {
|
||||
script.setAttribute('executed', 'boo');
|
||||
var s2 = script.cloneNode();
|
||||
assert_equals(s2.nonce, 'abc', 'IDL attribute');
|
||||
assert_equals(s2.getAttribute('nonce'), '');
|
||||
}, "Cloned node retains nonce.");
|
||||
|
||||
async_test(t => {
|
||||
var s2 = script.cloneNode();
|
||||
document.head.appendChild(s2);
|
||||
assert_equals(s2.nonce, 'abc');
|
||||
assert_equals(s2.getAttribute('nonce'), '');
|
||||
|
||||
window.addEventListener('load', t.step_func_done(_ => {
|
||||
// The cloned script won't execute, as its 'already started' flag is set.
|
||||
assert_equals(s2.getAttribute('executed'), 'boo');
|
||||
}));
|
||||
}, "Cloned node retains nonce when inserted.");
|
||||
|
||||
// Set the content attribute to 'foo'
|
||||
test(t => {
|
||||
script.setAttribute('nonce', 'foo');
|
||||
assert_equals(script.getAttribute('nonce'), 'foo');
|
||||
assert_equals(script.nonce, 'foo');
|
||||
}, "Writing 'nonce' content attribute.");
|
||||
|
||||
// Set the IDL attribute to 'bar'
|
||||
test(t => {
|
||||
script.nonce = 'bar';
|
||||
assert_equals(script.nonce, 'bar');
|
||||
assert_equals(script.getAttribute('nonce'), 'foo');
|
||||
}, "Writing 'nonce' IDL attribute.");
|
||||
|
||||
// Fragment parser.
|
||||
var documentWriteTest = async_test("Document-written script executes.");
|
||||
document.write(`<script nonce='abc'>
|
||||
documentWriteTest.done();
|
||||
test(t => {
|
||||
var script = document.currentScript;
|
||||
assert_equals(script.getAttribute('nonce'), '');
|
||||
assert_equals(script.nonce, 'abc');
|
||||
}, "Document-written script's nonce value.");
|
||||
</scr` + `ipt>`);
|
||||
|
||||
// Create node.
|
||||
async_test(t => {
|
||||
var s = document.createElement('script');
|
||||
s.innerText = script.innerText;
|
||||
s.nonce = 'abc';
|
||||
document.head.appendChild(s);
|
||||
assert_equals(s.nonce, 'abc');
|
||||
assert_equals(s.getAttribute('nonce'), null);
|
||||
|
||||
window.addEventListener('load', t.step_func_done(_ => {
|
||||
assert_equals(s.getAttribute('executed'), 'yay');
|
||||
}));
|
||||
}, "createElement.nonce.");
|
||||
|
||||
async_test(t => {
|
||||
var s = document.createElement('script');
|
||||
s.innerText = script.innerText;
|
||||
s.nonce = 'zyx';
|
||||
s.setAttribute('nonce', 'abc');
|
||||
assert_equals(s.nonce, 'abc');
|
||||
document.head.appendChild(s);
|
||||
assert_equals(s.nonce, 'abc');
|
||||
assert_equals(s.getAttribute('nonce'), '');
|
||||
|
||||
window.addEventListener('load', t.step_func_done(_ => {
|
||||
assert_equals(s.getAttribute('executed'), 'yay');
|
||||
}));
|
||||
}, "setAttribute('nonce') overwrites '.nonce' upon insertion.");
|
||||
|
||||
// Create node.
|
||||
async_test(t => {
|
||||
var s = document.createElement('script');
|
||||
s.innerText = script.innerText;
|
||||
s.setAttribute('nonce', 'abc');
|
||||
assert_equals(s.getAttribute('nonce'), 'abc', "Pre-insertion content");
|
||||
assert_equals(s.nonce, 'abc', "Pre-insertion IDL");
|
||||
document.head.appendChild(s);
|
||||
assert_equals(s.nonce, 'abc', "Post-insertion IDL");
|
||||
assert_equals(s.getAttribute('nonce'), '', "Post-insertion content");
|
||||
|
||||
window.addEventListener('load', t.step_func_done(_ => {
|
||||
assert_equals(s.getAttribute('executed'), 'yay');
|
||||
}));
|
||||
}, "createElement.setAttribute.");
|
||||
</script>
|
||||
|
||||
<!-- CSS Leakage -->
|
||||
<style>
|
||||
#cssTest { display: block; }
|
||||
#cssTest[nonce=abc] { background: url(/security/resources/abe.png); }
|
||||
</style>
|
||||
<script nonce="abc" id="cssTest">
|
||||
async_test(t => {
|
||||
requestAnimationFrame(t.step_func_done(_ => {
|
||||
var script = document.querySelector('#cssTest');
|
||||
var style = getComputedStyle(script);
|
||||
assert_equals(style['display'], 'block');
|
||||
assert_equals(style['background-image'], 'none');
|
||||
}));
|
||||
}, "Nonces don't leak via CSS side-channels.");
|
||||
</script>
|
|
@ -0,0 +1 @@
|
|||
Content-Security-Policy: script-src 'nonce-abc'; img-src 'none'
|
|
@ -0,0 +1,116 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<meta http-equiv="content-security-policy" content="script-src 'nonce-abc'; img-src 'none'">
|
||||
|
||||
<body>
|
||||
<!-- Basics -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<script nonce="abc" id="testScript">
|
||||
document.currentScript.setAttribute('executed', 'yay');
|
||||
</script>
|
||||
</svg>
|
||||
|
||||
<script nonce="abc">
|
||||
var script = document.querySelector('#testScript');
|
||||
|
||||
test(t => {
|
||||
// Query Selector
|
||||
assert_equals(document.querySelector('[nonce]'), script);
|
||||
assert_equals(document.querySelector('[nonce=""]'), null);
|
||||
assert_equals(document.querySelector('[nonce=abc]'), script);
|
||||
|
||||
assert_equals(script.getAttribute('nonce'), 'abc');
|
||||
assert_equals(script.nonce, 'abc');
|
||||
}, "Reading 'nonce' content attribute and IDL attribute.");
|
||||
|
||||
// Clone node.
|
||||
test(t => {
|
||||
script.setAttribute('executed', 'boo');
|
||||
var s2 = script.cloneNode();
|
||||
assert_equals(s2.nonce, 'abc', 'IDL attribute');
|
||||
assert_equals(s2.getAttribute('nonce'), 'abc');
|
||||
}, "Cloned node retains nonce.");
|
||||
|
||||
async_test(t => {
|
||||
var s2 = script.cloneNode();
|
||||
document.head.appendChild(s2);
|
||||
assert_equals(s2.nonce, 'abc');
|
||||
assert_equals(s2.getAttribute('nonce'), 'abc');
|
||||
|
||||
window.addEventListener('load', t.step_func_done(_ => {
|
||||
// The cloned script won't execute, as its 'already started' flag is set.
|
||||
assert_equals(s2.getAttribute('executed'), 'boo');
|
||||
}));
|
||||
}, "Cloned node retains nonce when inserted.");
|
||||
|
||||
// Set the content attribute to 'foo'
|
||||
test(t => {
|
||||
script.setAttribute('nonce', 'foo');
|
||||
assert_equals(script.getAttribute('nonce'), 'foo');
|
||||
assert_equals(script.nonce, 'abc');
|
||||
}, "Writing 'nonce' content attribute.");
|
||||
|
||||
// Set the IDL attribute to 'bar'
|
||||
test(t => {
|
||||
script.nonce = 'bar';
|
||||
assert_equals(script.nonce, 'bar');
|
||||
assert_equals(script.getAttribute('nonce'), 'foo');
|
||||
}, "Writing 'nonce' IDL attribute.");
|
||||
|
||||
// Fragment parser.
|
||||
var documentWriteTest = async_test("Document-written script executes.");
|
||||
document.write(`<svg xmlns="http://www.w3.org/2000/svg"><script nonce='abc'>
|
||||
documentWriteTest.done();
|
||||
test(t => {
|
||||
var script = document.currentScript;
|
||||
assert_equals(script.getAttribute('nonce'), 'abc');
|
||||
assert_equals(script.nonce, 'abc');
|
||||
}, "Document-written script's nonce value.");
|
||||
</scr` + `ipt></svg>`);
|
||||
|
||||
// Create node.
|
||||
test(t => {
|
||||
var s = document.createElement('svg');
|
||||
var innerScript = document.createElement('innerScript');
|
||||
innerScript.innerText = script.innerText;
|
||||
innerScript.nonce = 'abc';
|
||||
s.appendChild(innerScript);
|
||||
document.body.appendChild(s);
|
||||
assert_equals(innerScript.nonce, 'abc');
|
||||
assert_equals(innerScript.getAttribute('nonce'), null, 'innerScript.getAttribute nonce');
|
||||
}, "createElement.nonce.");
|
||||
|
||||
// Create node.
|
||||
test(t => {
|
||||
var s = document.createElement('svg');
|
||||
var innerScript = document.createElement('script');
|
||||
innerScript.innerText = script.innerText;
|
||||
innerScript.setAttribute('nonce', 'abc');
|
||||
assert_equals(innerScript.getAttribute('nonce'), 'abc', "Pre-insertion content");
|
||||
assert_equals(innerScript.nonce, 'abc', "Pre-insertion IDL");
|
||||
s.appendChild(innerScript);
|
||||
document.body.appendChild(s);
|
||||
assert_equals(innerScript.nonce, 'abc', "Post-insertion IDL");
|
||||
assert_equals(innerScript.getAttribute('nonce'), 'abc', "Post-insertion content");
|
||||
}, "createElement.setAttribute.");
|
||||
</script>
|
||||
|
||||
<!-- CSS Leakage -->
|
||||
<style>
|
||||
#cssTest { display: block; }
|
||||
#cssTest[nonce=abc] { background: url(/security/resources/abe.png); }
|
||||
</style>
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<script nonce="abc" id="cssTest">
|
||||
async_test(t => {
|
||||
requestAnimationFrame(t.step_func_done(_ => {
|
||||
var script = document.querySelector('#cssTest');
|
||||
var style = getComputedStyle(script);
|
||||
assert_equals(style['display'], 'block');
|
||||
assert_equals(style['background-image'], "url(\"http://web-platform.test:8001/security/resources/abe.png\")");
|
||||
}));
|
||||
}, "Nonces don't leak via CSS side-channels.");
|
||||
</script>
|
||||
</svg>
|
|
@ -0,0 +1,116 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js" nonce="abc"></script>
|
||||
<script src="/resources/testharnessreport.js" nonce="abc"></script>
|
||||
|
||||
<!-- `Content-Security-Policy: script-src 'nonce-abc'; img-src 'none'` delivered via headers -->
|
||||
|
||||
<body>
|
||||
<!-- Basics -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<script nonce="abc" id="testScript">
|
||||
document.currentScript.setAttribute('executed', 'yay');
|
||||
</script>
|
||||
</svg>
|
||||
|
||||
<script nonce="abc">
|
||||
var script = document.querySelector('#testScript');
|
||||
|
||||
test(t => {
|
||||
// Query Selector
|
||||
assert_equals(document.querySelector('body [nonce]'), script);
|
||||
assert_equals(document.querySelector('body [nonce=""]'), script);
|
||||
assert_equals(document.querySelector('body [nonce=abc]'), null);
|
||||
|
||||
assert_equals(script.getAttribute('nonce'), '');
|
||||
assert_equals(script.nonce, 'abc');
|
||||
}, "Reading 'nonce' content attribute and IDL attribute.");
|
||||
|
||||
// Clone node.
|
||||
test(t => {
|
||||
script.setAttribute('executed', 'boo');
|
||||
var s2 = script.cloneNode();
|
||||
assert_equals(s2.nonce, 'abc', 'IDL attribute');
|
||||
assert_equals(s2.getAttribute('nonce'), '');
|
||||
}, "Cloned node retains nonce.");
|
||||
|
||||
async_test(t => {
|
||||
var s2 = script.cloneNode();
|
||||
document.head.appendChild(s2);
|
||||
assert_equals(s2.nonce, 'abc');
|
||||
assert_equals(s2.getAttribute('nonce'), '');
|
||||
|
||||
window.addEventListener('load', t.step_func_done(_ => {
|
||||
// The cloned script won't execute, as its 'already started' flag is set.
|
||||
assert_equals(s2.getAttribute('executed'), 'boo');
|
||||
}));
|
||||
}, "Cloned node retains nonce when inserted.");
|
||||
|
||||
// Set the content attribute to 'foo'
|
||||
test(t => {
|
||||
script.setAttribute('nonce', 'foo');
|
||||
assert_equals(script.getAttribute('nonce'), 'foo');
|
||||
assert_equals(script.nonce, 'abc');
|
||||
}, "Writing 'nonce' content attribute.");
|
||||
|
||||
// Set the IDL attribute to 'bar'
|
||||
test(t => {
|
||||
script.nonce = 'bar';
|
||||
assert_equals(script.nonce, 'bar');
|
||||
assert_equals(script.getAttribute('nonce'), 'foo');
|
||||
}, "Writing 'nonce' IDL attribute.");
|
||||
|
||||
// Fragment parser.
|
||||
var documentWriteTest = async_test("Document-written script executes.");
|
||||
document.write(`<svg xmlns="http://www.w3.org/2000/svg"><script nonce='abc'>
|
||||
documentWriteTest.done();
|
||||
test(t => {
|
||||
var script = document.currentScript;
|
||||
assert_equals(script.getAttribute('nonce'), '');
|
||||
assert_equals(script.nonce, 'abc');
|
||||
}, "Document-written script's nonce value.");
|
||||
</scr` + `ipt></svg>`);
|
||||
|
||||
// Create node.
|
||||
test(t => {
|
||||
var s = document.createElement('svg');
|
||||
var innerScript = document.createElement('script');
|
||||
innerScript.innerText = script.innerText;
|
||||
innerScript.nonce = 'abc';
|
||||
s.appendChild(innerScript);
|
||||
document.body.appendChild(s);
|
||||
assert_equals(innerScript.nonce, 'abc');
|
||||
assert_equals(innerScript.getAttribute('nonce'), null);
|
||||
}, "createElement.nonce.");
|
||||
|
||||
// Create node.
|
||||
test(t => {
|
||||
var s = document.createElement('svg');
|
||||
var innerScript = document.createElement('script');
|
||||
innerScript.innerText = script.innerText;
|
||||
innerScript.setAttribute('nonce', 'abc');
|
||||
assert_equals(innerScript.getAttribute('nonce'), 'abc', "Pre-insertion content");
|
||||
assert_equals(innerScript.nonce, 'abc', "Pre-insertion IDL");
|
||||
s.appendChild(innerScript);
|
||||
document.body.appendChild(s);
|
||||
assert_equals(innerScript.nonce, 'abc', "Post-insertion IDL");
|
||||
assert_equals(innerScript.getAttribute('nonce'), '', "Post-insertion content");
|
||||
}, "createElement.setAttribute.");
|
||||
</script>
|
||||
|
||||
<!-- CSS Leakage -->
|
||||
<style>
|
||||
#cssTest { display: block; }
|
||||
#cssTest[nonce=abc] { background: url(/security/resources/abe.png); }
|
||||
</style>
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<script nonce="abc" id="cssTest">
|
||||
async_test(t => {
|
||||
requestAnimationFrame(t.step_func_done(_ => {
|
||||
var script = document.querySelector('#cssTest');
|
||||
var style = getComputedStyle(script);
|
||||
assert_equals(style['display'], 'block');
|
||||
assert_equals(style['background-image'], 'none');
|
||||
}));
|
||||
}, "Nonces don't leak via CSS side-channels.");
|
||||
</script>
|
||||
</svg>
|
|
@ -0,0 +1 @@
|
|||
Content-Security-Policy: script-src 'nonce-abc'; img-src 'none'
|
|
@ -0,0 +1,31 @@
|
|||
<!doctype html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="./support/testharness-helper.sub.js"></script>
|
||||
<body></body>
|
||||
<script>
|
||||
function waitForViolation(el, t, policy, blocked_origin) {
|
||||
return new Promise(resolve => {
|
||||
el.addEventListener('securitypolicyviolation', e => {
|
||||
if (e.originalPolicy == policy && (new URL(e.blockedURI)).origin == blocked_origin)
|
||||
resolve(e);
|
||||
else
|
||||
t.unreached_func("Unexpected violation event for " + e.blockedURI)();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async_test(t => {
|
||||
var i = document.createElement("img");
|
||||
var redirect = generateCrossOriginRedirectImage();
|
||||
i.src = redirect.url;
|
||||
|
||||
// Report-only policy should trigger a violation on the redirected request.
|
||||
waitForViolation(window, t, "img-src https:", (new URL(redirect.target)).origin).then(t.step_func(e => {
|
||||
t.done();
|
||||
}));
|
||||
|
||||
document.body.appendChild(i);
|
||||
}, "Image that redirects to http:// URL prohibited by Report-Only must generate a violation report, even with upgrade-insecure-requests");
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,2 @@
|
|||
Content-Security-Policy-Report-Only: img-src https:
|
||||
Content-Security-Policy: upgrade-insecure-requests
|
|
@ -0,0 +1,5 @@
|
|||
function generateCrossOriginRedirectImage() {
|
||||
var target = "http://{{host}}:{{ports[https][0]}}/content-security-policy/support/pass.png";
|
||||
var url = "/common/redirect.py?location=" + encodeURIComponent(target);
|
||||
return { url: url, target: target }
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
<!doctype html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/upgrade-insecure-requests/support/testharness-helper.sub.js"></script>
|
||||
<body></body>
|
||||
<script>
|
||||
function waitForViolation(el, effective_directive) {
|
||||
return new Promise(resolve => {
|
||||
el.addEventListener('securitypolicyviolation', e => {
|
||||
if (e.effectiveDirective == effective_directive)
|
||||
resolve(e);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async_test(t => {
|
||||
var url = generateURL(Host.SAME_ORIGIN, Protocol.INSECURE, ResourceType.IMAGE).url;
|
||||
var i = document.createElement('img');
|
||||
var loaded = false;
|
||||
var reported = false;
|
||||
waitForViolation(window, "img-src")
|
||||
.then(t.step_func(e => {
|
||||
reported = true;
|
||||
if (loaded)
|
||||
t.done();
|
||||
}));
|
||||
i.onload = t.step_func(_ => {
|
||||
loaded = true;
|
||||
if (reported)
|
||||
t.done();
|
||||
});
|
||||
i.onerror = t.unreached_func(url + " should load successfully.");
|
||||
i.src = url;
|
||||
document.body.appendChild(i);
|
||||
}, "Upgraded image is reported");
|
||||
|
||||
async_test(t => {
|
||||
var url = generateURL(Host.SAME_ORIGIN, Protocol.INSECURE, ResourceType.FRAME).url;
|
||||
var i = document.createElement('iframe');
|
||||
var loaded = false;
|
||||
var reported = false;
|
||||
waitForViolation(window, "frame-src")
|
||||
.then(t.step_func(e => {
|
||||
reported = true;
|
||||
if (loaded)
|
||||
t.done();
|
||||
}));
|
||||
window.addEventListener("message", t.step_func(e => {
|
||||
if (e.source == i.contentWindow) {
|
||||
i.remove();
|
||||
loaded = true;
|
||||
if (reported)
|
||||
t.done();
|
||||
}
|
||||
}));
|
||||
i.src = url;
|
||||
document.body.appendChild(i);
|
||||
}, "Upgraded iframe is reported");
|
||||
|
||||
async_test(t => {
|
||||
// Load an HTTPS iframe, then navigate it to an HTTP URL and check that the HTTP URL is both upgraded and reported.
|
||||
var url = generateURL(Host.SAME_ORIGIN, Protocol.SECURE, ResourceType.FRAME).url;
|
||||
var navigate_to = generateURL(Host.CROSS_ORIGIN, Protocol.INSECURE, ResourceType.FRAME).url;
|
||||
var upgraded = new URL(navigate_to);
|
||||
upgraded.protocol = "https";
|
||||
|
||||
var i = document.createElement('iframe');
|
||||
var loaded = false;
|
||||
var reported = false;
|
||||
|
||||
window.addEventListener("message", t.step_func(e => {
|
||||
if (e.source == i.contentWindow) {
|
||||
if (e.data == (new URL(url)).origin) {
|
||||
waitForViolation(window, "frame-src")
|
||||
.then(t.step_func(e => {
|
||||
reported = true;
|
||||
if (loaded)
|
||||
t.done();
|
||||
}));
|
||||
i.contentWindow.location.href = navigate_to;
|
||||
} else if (e.data == (new URL(upgraded)).origin) {
|
||||
loaded = true;
|
||||
if (reported)
|
||||
t.done();
|
||||
}
|
||||
}
|
||||
}));
|
||||
i.src = url;
|
||||
document.body.appendChild(i);
|
||||
}, "Navigated iframe is upgraded and reported");
|
||||
</script>
|
||||
</html>
|
|
@ -0,0 +1,2 @@
|
|||
Content-Security-Policy-Report-Only: frame-src https:; img-src https:
|
||||
Content-Security-Policy: upgrade-insecure-requests
|
Loading…
Add table
Add a link
Reference in a new issue