More Content Security Policy with report-to
Sending even more Content Security Policy (CSP) violation reports with report-to, asynchronously. Read general CSP reporting description for more details.
The CSP response header:
Content-Security-Policy: default-src 'none'; img-src 'self' https://www.michalspacek.cz; script-src 'nonce-1hNjWX7sOwQRSEG/WKRl+ix2' 'self' 'report-sample'; style-src 'self' 'nonce-1hNjWX7sOwQRSEG/WKRl+ix2'; form-action 'self'; report-to default
default-src: what's allowed by default, includes images, fonts, JavaScript and more-
img-src: where to load images from, overridesdefault-srcfor images'self'means current URL's origin (scheme + host + port)
-
script-src: what JavaScript is allowed to be executed'nonce-1hNjWX7sOwQRSEG/WKRl+ix2'meansscriptelements withnonce="1hNjWX7sOwQRSEG/WKRl+ix2"attribute'report-sample'instructs the browser to include the first 40 characters of the blocked JavaScript in the report
style-src: allowed CSS sourcesform-action: where it's allowed to submit forms, not part ofdefault-srcreport-to: name of the endpoint where to send violation reports, as defined in theReporting-Endpointsheader
The Reporting-Endpoints response header:
Reporting-Endpoints: default="https://easel.has.report/report"
default: the name of the endpoint, the same as in the CSP header in thereport-todirective"url": where to send reports, must behttps://, otherwise the endpoint will be ignored-
You may provide multiple
name="url"endpoints separated by comma (,)- For example:
Reporting-Endpoints: csp-reporting="https://example.com/csp", nel-reporting="https://example.com/nel"
- For example:
Load any image
<script nonce="1hNjWX7sOwQRSEG/WKRl+ix2">
document.getElementById('prompt-image').onclick = function() {
const url = prompt('Enter a URL to be used for an image', 'https://');
if (url) {
new Image().src = url;
alert('Tried loading an image from ' + url);
}
}
</script>
- Allowed or blocked depending on what URL you enter, only some images are allowed to load, see the CSP header above
- Check your reports (can take some time before the browser sends the report) – if blocked, a report will be sent
… any JavaScript file
<script nonce="1hNjWX7sOwQRSEG/WKRl+ix2">
document.getElementById('prompt-javascript').onclick = function() {
const url = prompt('Enter a URL to load a JS file from', 'https://');
if (url) {
const script = document.createElement('script');
script.src = url;
document.getElementById('prompt-javascript').insertAdjacentElement('afterend', script);
alert('Tried loading a JS file from ' + url);
}
}
</script>
- Allowed or blocked depending on what URL you enter, only some JS is allowed to load, see the CSP header above
- Check your reports (can take some time before the browser sends the report) – if blocked, a report will be sent
… any CSS file
<script nonce="1hNjWX7sOwQRSEG/WKRl+ix2">
document.getElementById('prompt-css').onclick = function() {
const url = prompt('Enter a URL to load a CSS file from', 'https://');
if (url) {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = url;
document.getElementById('prompt-javascript').insertAdjacentElement('afterend', link);
alert('Tried loading a CSS file from ' + url);
}
}
</script>
- Allowed or blocked depending on what URL you enter, only some CSS is allowed to load, see the CSP header above
- Check your reports (can take some time before the browser sends the report) – if blocked, a report will be sent
Submit a form anywhere
With form-action, you can limit where forms on your page can be submitted,
so if an attacker would inject a fake form or would change the action of your existing form, the browser wouldn't submit it.
Please note that form-action is not part of the default-src fallback, and needs to be explicitly specified if you want to limit where forms are to be submitted.
<script nonce="1hNjWX7sOwQRSEG/WKRl+ix2">
document.getElementById('prompt-form').onclick = function() {
const url = prompt('Enter a URL where to submit a form to', 'https://');
if (url) {
const form = document.getElementById('submitForm');
if (form) {
form.setAttribute('action', url);
form.submit();
} else {
const form = document.createElement('form');
form.setAttribute('method', 'post');
form.setAttribute('class', 'hidden');
form.setAttribute('action', url);
form.setAttribute('id', 'submitForm');
const text = document.createElement('input');
text.setAttribute('type', 'text');
text.setAttribute('value', 'text value');
form.appendChild(text);
const hidden = document.createElement('input');
hidden.setAttribute('type', 'hidden');
hidden.setAttribute('value', 'hidden value');
form.appendChild(hidden);
document.getElementById('prompt-form').insertAdjacentElement('afterend', form);
form.submit();
}
alert('Submitted a form to ' + url);
}
}
</script>
- Allowed or blocked depending on what URL you enter, forms are not allowed to be submitted anywhere, see the CSP header above
- Check your reports (can take some time before the browser sends the report) – if blocked, a report will be sent
Related specs & documents
- Content Security Policy Level 3 Working Draft
- Content Security Policy Level 2
- Content Security Policy 1.0 (discontinued)
- Reporting API Working Draft
- Reporting API Editor's Draft (which will evolve into a Working Draft, followed by a Recommendation eventually)