Trusted Types
In JavaScript, Trusted Types allow you to restrict the use of unsafe API's like '.innerHTML
'.
It provides very effective protection against DOM-based Cross-Site-Scripting vulnerabilities.
This is done by simply making unsafe API's reject any value that's not Trusted.
To enable, update your 'Content-Security-Policy
' header to include:
Content-Security-Policy: require-trusted-types-for 'script'; trusted-types 'none';
If your browser understands Trusted Types, anything like the following will be rejected:
document.body.innerHTML = location.href;
While this gives full protection; you may need to Trust some values...
1. Define a policy (object) with certain magic methods, where the browser will Trust the returned values:
var my_policy = {
'createHTML': function (s) {
// You should check/cleanup the string, or get the
// output from a trusted library, e.g. DOMPurify.sanitize().
return s;
}
};
if (window.trustedTypes) { // Only supporting browsers
my_policy = trustedTypes.createPolicy('example', my_policy);
}
2. The `createPolicy()` takes a unique name, e.g 'example'. Add this to your CSP header (no quotes):
Content-Security-Policy: require-trusted-types-for 'script'; trusted-types example;
3. Now your policy can be used as needed:
document.body.innerHTML = '<p>Hi</p>'; // Rejected
document.body.innerHTML = my_policy.createHTML('<p>Hi</p>'); // Accepted
You can try this example on this page, using your browsers developer tools (CSP allows 'example')
While your policy should check/cleanup values, it could simply be used to identify code that needs auditing.
Ideally you won't need your own policy, and instead use safe API's like `document.createElement('img')`.
Hopefully fromLiteral will exist soon, which simply trusts any developer defined string (template literals), creating a safer/easier method that doesn't use a policy, e.g.
document.body.innerHTML = TrustedHTML.fromLiteral`<p>Hi</p>`;
And while DOMPurify already supports Trusted Types, hopefully the HTML Sanitizer API will also exist soon.
Regarding Ending Injection Vulnerabilities, other languages may implement this idea slightly differently; e.g. a library could create a "Stringable Value-Object" for their output, and those objects can then be trusted for certain unsafe API's.