Trusted Types / require-trusted-types-for: stopping DOM XSS sinks
Chrome reports “This document requires ‘TrustedHTML’ assignment” when your code sets innerHTML with a plain string. Trusted Types force every risky DOM sink to go through a named policy you control.
What Trusted Types are for
Classic CSP stops the browser loading or running unexpected scripts. DOM XSS often bypasses that: the page already ran your code, then that code did el.innerHTML = userInput. Trusted Types make those sinks type-safe. With the policy on, a bare string is rejected; only a TrustedHTML, TrustedScript or TrustedScriptURL created by a policy you registered may be assigned.
The CSP directives
Content-Security-Policy:
require-trusted-types-for 'script';
trusted-types dompurify default;
| Directive | Meaning |
|---|---|
require-trusted-types-for 'script' | Enforce Trusted Types on script-ish sinks: innerHTML, outerHTML, insertAdjacentHTML, document.write, eval/Function (where applicable), script.src, script.text, and similar |
trusted-types name1 name2 | Allow-list of policy names trustedTypes.createPolicy may register |
trusted-types default | Allows a policy literally named default, used automatically by some sinks / libraries |
trusted-types * | Any policy name (weak; prefer an explicit list) |
trusted-types 'allow-duplicates' | Lets the same name be created twice (useful with duplicate bundles); combine with names |
Support is strongest in Chromium. Firefox and Safari are catching up; unsupported browsers ignore the directives, so keep your sanitiser logic anyway.
Minimal policy example
// Only after the CSP allows this policy name:
const policy = trustedTypes.createPolicy('dompurify', {
createHTML: (dirty) => DOMPurify.sanitize(dirty, {RETURN_TRUSTED_TYPE: false}),
createScriptURL: (url) => {
const u = new URL(url, location.href);
if (u.origin !== location.origin) throw new TypeError('blocked script URL');
return u.href;
},
});
el.innerHTML = policy.createHTML(userHtml); // TrustedHTML
s.src = policy.createScriptURL('/js/widget.js');
Never write a policy that returns its input unchanged (createHTML: s => s) unless the value is already known-safe constants — that reopens the sink.
Console errors you will see
This document requires 'TrustedHTML' assignment.— a string hitinnerHTML/outerHTML/insertAdjacentHTML.This document requires 'TrustedScriptURL' assignment.— a string hitscript.srcor similar.Failed to execute 'createPolicy' on 'TrustedTypePolicyFactory': Policy "x" disallowed.— the name is not in thetrusted-typesallow-list.
Rollout tips
- Start with
Content-Security-Policy-Report-Only: require-trusted-types-for 'script'; trusted-types default dompurify(see Report-Only vs Enforce). - Fix first-party code and known libraries (DOMPurify, lit, Angular have Trusted Types modes).
- Third-party widgets that assign
innerHTMLfreely may need a narrow policy or to be sandboxed in an iframe with a looser policy. - Enforce once reports are quiet. Keep a normal
script-srcpolicy too — Trusted Types complement CSP, they do not replace it. Check the whole header in the CSP explainer.
Related
CSP header explainer · CSP Report-Only vs Enforce · Refused to execute inline script · Refused to connect (connect-src) · Anvil CSP checker API
Questions
What is require-trusted-types-for 'script'?
A CSP directive that makes the browser reject raw strings in dangerous DOM sinks like innerHTML and script.src unless they are Trusted Types created by an allowed policy.
Do I still need script-src if I use Trusted Types?
Yes. Trusted Types stop DOM XSS sinks; script-src still controls which scripts can load and run.
Why does createPolicy throw 'disallowed'?
Your CSP trusted-types list does not include that policy name. Add the name, or use trusted-types * only while debugging.
Does Trusted Types work in Firefox and Safari?
Chromium has had support longest. Other engines are adding it; feature-detect trustedTypes and keep sanitising either way.
Is a passthrough createHTML: s => s safe?
No. That disables the protection. The policy must sanitise, allow-list constants, or otherwise prove the value is safe.
Published .