Skip to content

require-trusted-types-for

require-trusted-types-for 'script' makes the dangerous DOM sinks - innerHTML, outerHTML, document.write, script.src, eval - reject plain strings. Only a TrustedHTML, TrustedScript or TrustedScriptURL produced by a policy is accepted.

This is the strongest anti-XSS measure CSP offers, and the only one that addresses DOM XSS rather than injected markup. It works by shrinking the number of places a string can become code to a handful of reviewable policy functions.

It is one half of a pair: this directive enforces the sinks, and trusted-types controls which policies may exist.

Content-Security-Policy: require-trusted-types-for 'script';
  • Assignments to DOM XSS injection sinks, such as Element.innerHTML.
  • Values passed to script-URL sinks, such as HTMLScriptElement.src.

require-trusted-types-for has no fallback. default-src does not enable it, and without it the trusted-types directive enforces nothing at the sinks.

Content-Security-Policy: require-trusted-types-for 'script'; trusted-types default
  • 'script' is the only defined value. The interesting configuration is in the trusted-types directive next to it.
  • Roll it out in report-only first. The violations name the sink and the first 40 characters of the offending value, which is enough to find the code - and there will be more of them than you expect, because third-party libraries use these sinks freely.

A value that went through a policy:

const policy = trustedTypes.createPolicy("default", {
createHTML: (input) => DOMPurify.sanitize(input),
});
el.innerHTML = policy.createHTML(untrusted);

A plain string - throws a TypeError and reports:

el.innerHTML = untrusted;
  • Baseline 2026: newly available. It works across the latest versions of every major browser as of February 2026; for years before that it was Chromium-only.
  • In a browser without support the directive is ignored, so the code still has to be correct without it. Treat Trusted Types as defence in depth on top of a strict script-src, not as a replacement for one.
Field Value
violatedDirective require-trusted-types-for
effectiveDirective require-trusted-types-for
blockedUri trusted-types-sink
Issue title require-trusted-types-for sink Element innerHTML
  • blockedUri is the literal string trusted-types-sink; there is no URL. The sample carries the sink name followed by the first 40 characters of the value, and browsers include it for Trusted Types violations without needing 'report-sample'.
  • There is no host to group on, so issues are grouped by the sink name - the half of the sample before the |. One issue per sink the page assigns to, whatever it assigned. Grouping on the whole sample would instead open a fresh issue for every distinct value, which for el.innerHTML = userContent is every page view.

Point your policy’s report-uri at your site’s HeaderHawk endpoint and the violations above arrive in the dashboard, grouped as described. The Quick Start sets that up in five minutes, and the integration guides cover the header syntax for each platform.