Trusted Types
Trusted Types is a browser-enforced policy: dangerous DOM sinks (innerHTML, script.src) refuse plain strings — they require typed values created by a policy you control. XSS becomes impossible if you skip the policy.
Enable CSP, define a policy, use it
EXAMPLE
// 1) Tell the browser to enforce Trusted Types via CSP
// Server header:
// Content-Security-Policy: require-trusted-types-for 'script';
// trusted-types app dompurify
// 2) Define a policy (typically once at app bootstrap)
import DOMPurify from 'dompurify';
const policy = trustedTypes.createPolicy('app', {
createHTML: (input) => DOMPurify.sanitize(input),
createScript: (_) => '', // refuse all dynamic scripts
createScriptURL: (url) => {
const u = new URL(url, location.href);
if (u.origin !== location.origin) throw new TypeError('cross-origin script blocked');
return u.toString();
},
});
// 3) Use the policy when assigning to dangerous sinks
element.innerHTML = policy.createHTML(userHtml);
script.src = policy.createScriptURL('/lazy-loaded.js');
// 4) Plain strings now THROW
element.innerHTML = '<p>plain</p>';
// → TypeError: Failed to set the 'innerHTML' property on 'Element':
// This document requires 'TrustedHTML' assignment.
// 5) For frameworks — they typically register their own policy
// Angular: built-in support via DomSanitizer
// React 19+: explicit Trusted Types policy via 'trustedTypes' prop on root
// Lit / Stencil: support automatically when CSP is set
// 6) Report-only first, enforce after
Content-Security-Policy-Report-Only:
require-trusted-types-for 'script';
trusted-types app;
report-uri /csp-report
// Collect violation reports, fix legitimate sinks, then flip to enforcing.
// 7) Combine with CSP nonces for the full picture
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-rAnd0m' 'strict-dynamic';
require-trusted-types-for 'script';
trusted-types app dompurify;
object-src 'none';
base-uri 'self'
Why it matters
Trusted Types is the closest thing to “XSS off by default” the web has. Pair it with nonce-based CSP and the impact of a single missed sanitisation drops from RCE-in-the-browser to nothing.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
// Lock down dangerous sinks at the browser level.
// Set CSP header:
// Content-Security-Policy: require-trusted-types-for 'script'
// And create / use a single policy:
const policy = trustedTypes.createPolicy('app', {
createHTML: s => DOMPurify.sanitize(s),
});
element.innerHTML = policy.createHTML(userHtml);
Try it Yourself »
Exercise
CSP directive that enables Trusted Types.
Content-Security-Policy: require-
-for 'script'
Hyphenated.
Discussion
Loading…