report-uri
Sending Content Security Policy (CSP) violation reports.
CSP is a policy that lets the authors (or server administrators) of a web application inform the browser about the sources from which the application expects to load resources like images, scripts, styles, or even where to submit forms.
Content Security Policy is not intended as a first line of defense against content injection vulnerabilities like Cross-Site Scripting (XSS). Instead, CSP is best used as defense-in-depth, to reduce the harm caused by content injection attacks.
Using report-uri
directive is specific to CSP and is not part of the Reporting API specification, and is actually deprecated and replaced by report-to
directive and Reporting API in Content Security Policy level 3 spec, which is not yet fully supported by all major clients.
To support more browsers, apps usually send both report-uri
and report-to
in their CSP headers.
Content-Security-Policy: default-src 'none'; img-src 'self' https://www.michalspacek.cz; script-src 'nonce-0oxZPV1g5wSSJMznBsEiT0Pu' 'self' 'report-sample'; style-src 'self' 'nonce-0oxZPV1g5wSSJMznBsEiT0Pu'; report-uri https://boyce.has.report/report
default-src
: what's allowed by default, includes images, fonts, JavaScript and moreimg-src
: where to load images from, overrides default-src
for images
'self'
means current URL's origin (scheme + host + port)script-src
: what JavaScript is allowed to be executed
'nonce-0oxZPV1g5wSSJMznBsEiT0Pu'
means script
elements with nonce="0oxZPV1g5wSSJMznBsEiT0Pu"
attribute'report-sample'
instructs the browser to include the first 40 characters of the blocked JavaScript in the reportstyle-src
: allowed CSS sourcesreport-uri
: where to send violation reports toanother image from https://www.michalspacek.cz (allowed)
<script nonce="0oxZPV1g5wSSJMznBsEiT0Pu">
document.getElementById('allowed').onclick = function(e) {
document.getElementById('image').src = 'https://www.michalspacek.cz/i/images/photos/michalspacek-webtop100-400x268.jpg';
}
</script>
Now simulate an attacker:
an image from https://example.com
<script nonce="0oxZPV1g5wSSJMznBsEiT0Pu">
document.getElementById('blocked').onclick = function(e) {
document.getElementById('image').src = 'https://example.com/image.png';
}
</script>
(allowed, the script
tag contains nonce="0oxZPV1g5wSSJMznBsEiT0Pu"
)
<script nonce="0oxZPV1g5wSSJMznBsEiT0Pu">
document.getElementById('js').onclick = function(e) {
alert('hi');
};
</script>
Simulate an attacker:
blocked JS tag
<script nonce="0oxZPV1g5wSSJMznBsEiT0Pu">
document.getElementById('inject').onclick = function() {
const script = document.createElement('script');
script.text = 'console.log("lo")';
document.getElementById('inject').insertAdjacentElement('afterend', script);
}
</script>
document.createElement()
doesn't have a nonce
<button id="inject">