--- title: "Trusted Types" category: security status: recommended url: https://webspecification.com/spec/security/trusted-types/ updated: "2026-06-23T10:00:00.000Z" sources: - title: "Trusted Types (W3C Working Draft)" url: "https://www.w3.org/TR/trusted-types/" publisher: "W3C" - title: "MDN — Trusted Types API" url: "https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API" publisher: "MDN" - title: "MDN — Content-Security-Policy: require-trusted-types-for" url: "https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/require-trusted-types-for" publisher: "MDN" - title: "OWASP — DOM based XSS Prevention Cheat Sheet" url: "https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html" publisher: "OWASP" source_repo: undefined licence: CC-BY-4.0 --- # Trusted Types > Trusted Types make the browser reject plain strings at DOM injection sinks like innerHTML, demanding a vetted typed value instead. Switched on with two CSP directives, it neutralises a whole class of DOM-based XSS. ## What it is Trusted Types is a browser mechanism that blocks DOM-based cross-site scripting at the point of injection. DOM XSS happens when an attacker-controlled string reaches a dangerous "sink" — `innerHTML`, `outerHTML`, `document.write()`, `eval()`, or a script element's `src`. Trusted Types makes the browser refuse a plain string at those sinks and demand a non-spoofable typed value (`TrustedHTML`, `TrustedScript`, or `TrustedScriptURL`) produced by a policy you define and control. You enable it with two Content Security Policy directives: ```http Content-Security-Policy: require-trusted-types-for 'script'; trusted-types escape ``` It reached [Baseline](https://web.dev/baseline) in February 2026 — Chrome and Edge have shipped it since 2020, Safari since version 26, and Firefox completed the set. ## Why it matters A nonce-based [CSP](/spec/security/content-security-policy/) stops an attacker injecting or running a new external script, but DOM XSS needs no new script element: it abuses code already on the page that writes untrusted input into a sink. Take a search widget that echoes the query from the URL: ```js // Vulnerable: q comes straight from the address bar const q = new URLSearchParams(location.search).get("q"); results.innerHTML = `

Results for ${q}

`; ``` A visitor sent to `?q=` runs the attacker's script in your origin — the `onerror` handler fires the moment the broken image loads, and the session cookie leaves the building. No external script, no CSP `script-src` violation; a nonce never gets a look-in. Trusted Types closes that gap. With `require-trusted-types-for 'script'` enforced, that `innerHTML` assignment throws a `TypeError` before the string ever reaches the parser, because `q` is a plain string and not a `TrustedHTML` value. To make the page work again you must route the value through a policy that sanitises it: ```js const policy = trustedTypes.createPolicy("escape", { createHTML: (s) => DOMPurify.sanitize(s), }); results.innerHTML = policy.createHTML(`

Results for ${q}

`); ``` The `` is now stripped before it lands. The win is structural: the question stops being "did every developer remember to sanitise every sink?" and becomes "does *any* sink receive an unsanitised string?" — and the browser answers that for you, everywhere, by throwing. This covers more than `innerHTML`. The three trusted types guard the three families of script-execution sink: - **`TrustedHTML`** — markup parsers: `innerHTML`, `outerHTML`, `document.write()`, `insertAdjacentHTML()`, `