DOM-based XSS Injection Sinks Detection with Trusted Types and Content Security Policy with report-uri
When you use Trusted Types, and a plain string is passed to a so-called sink like the innerHTML
or the document.write()
method without it being escaped by the Trusted Types policy, a report is generated by the browser.
If the policy is enforced, the string will not be passed to the sink, protecting your app against DOM-based cross-site scripting (XSS) attacks.
However, when starting with Trusted Types, you may want to first check how many of those sinks you're actually using, so you can plan ahead and fix the violations before they break your app.
With the following Content-Security-Policy-Report-Only
header, your app or website will continue to work normally, but you'll receive a report whenever something uses a sink.
The CSPRO (CSP Report-Only) response header:
Content-Security-Policy-Report-Only: require-trusted-types-for 'script'; report-uri https://virgil.has.report/report
-
require-trusted-types-for 'script'
: enable Trusted Types for DOM XSS sinks ('script'
is the only available value) -
report-uri
: where to send violation reports to- Reporting would also work with the
report-to
directive, see the CSP demo, but let's keep things simple here
- Reporting would also work with the
DOM-based XSS
<script>
document.getElementById('prompt-xss').onclick = function() {
const html = prompt('Enter any HTML', 'foo <strong>bar</strong>');
if (html) {
document.getElementById('xss-me').innerHTML = html;
}
}
</script>
- Allowed
- Would be blocked if the policy was enforced and not report-only
- Will trigger a report, check Developer tools (Network and Console tabs)
- Check your reports
Related specs & documents
- My article about DOM XSS and Trusted Types (also available in Czech)
- Trusted Types Editor's Draft
- Prevent DOM-based cross-site scripting vulnerabilities with Trusted Types on web.dev
- Trusted Types API on MDN