Prevent DOM-based XSS with Trusted Types and Content Security Policy with report-uri
Once Trusted Types are enabled, then when a plain string is being 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.
The string will not actually be passed to the sink, if the policy is enforced. This will protect your app against DOM-based cross-site scripting (XSS) attacks.
However, you may need to update your application to call the policy.createHTML() method when assigning data to a sink like the innerHTML property.
But you can also create a policy called default, which will be automatically called whenever a string is used in a sink that only accepts Trusted Types.
The CSP response header:
Content-Security-Policy: require-trusted-types-for 'script'; report-uri https://rank.has.report/report
Trusted Types with a default policy
#html sink: …
<script>
trustedTypes.createPolicy('default', {
createHTML: string => string.replaceAll('<', '<'),
});
document.getElementById('prompt-html').onclick = function() {
const html = prompt('Enter any HTML', 'foo <strong>bar</strong>');
if (html) {
document.getElementById('html').innerHTML = html;
}
}
</script>
The #html sink:
- Is allowed in a way that it will display the HTML you've entered, automatically escaped by the default policy
-
Behind the scenes, it uses the
createHTML()method of thedefaultpolicy created bytrustedTypes.createPolicy()- … to replace all
<("less than") characters with<entity, a very simple and naive escaping function
- … to replace all
-
If you enter let's say
<em>, this is what happens automatically, behind the scenes:createHTML()will convert it to<em>- Wrap it in a
TrustedHTMLobject - And pass it to the
innerHTMLsink
- Note that your browser, not the policy, will convert
>to>as well, so in Developer Tools you will see<em>
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