← Back to Blog

Trusted Types block the DOM XSS attacks that CSP alone cannot stop

Trusted Types block the DOM XSS attacks that CSP alone cannot stop

Content Security Policy is the most widely recommended defense against cross-site scripting. And for server-reflected XSS, it works well. A strict CSP with nonce-based script allowlisting prevents the browser from executing injected script tags. But there is an entire class of XSS that CSP does not touch: DOM-based XSS.

DOM XSS happens when client-side JavaScript takes untrusted input and passes it to a dangerous API like innerHTML, document.write, or eval. The attack never involves a script tag. The malicious code flows through legitimate JavaScript functions into DOM sinks that interpret strings as HTML or code. CSP sees nothing wrong because no policy violation occurred.

The sink problem

The DOM has about 60 APIs that accept strings and interpret them as HTML, JavaScript, or URLs. These are called injection sinks. The most common are innerHTML, outerHTML, document.write, eval, setTimeout with string arguments, and location.href assignments.

When any of these sinks receives attacker-controlled input, the browser executes whatever code is embedded in that input. A user-supplied search query that gets inserted via innerHTML without sanitization is all it takes.

Traditional defenses rely on developer discipline: sanitize every input, escape every output, review every code path. This works in theory. In practice, one missed sink in a codebase of thousands of JavaScript files is enough.

How Trusted Types work

Trusted Types is a browser API that changes the rules. Instead of trusting developers to sanitize correctly every time, it makes the browser enforce the rule: dangerous sinks only accept Trusted Type objects, not raw strings.

You enable it via CSP:

Content-Security-Policy: require-trusted-types-for 'script'

With this header, any attempt to assign a raw string to innerHTML or pass a string to eval throws a TypeError. The code must create a TrustedHTML, TrustedScript, or TrustedScriptURL object through a policy function that performs sanitization. No policy, no execution.

This flips the security model. Instead of hoping every developer remembers to sanitize, the browser blocks execution unless sanitization provably happened. The attack surface shrinks from "every sink in the codebase" to "the policy functions."

What the audit checks

The Trusted Types Audit checks two things. First, whether your CSP includes require-trusted-types-for 'script' to enable enforcement. Second, it scans your page's JavaScript for raw DOM sink usage that would violate a Trusted Types policy.

It identifies every innerHTML assignment, every document.write call, every eval invocation, and every other sink in your client-side code. These are the locations that would break under Trusted Types enforcement and that need to be wrapped in policy functions.

This gives you a migration path. You see exactly how many sinks exist, where they are, and what needs to change before you can flip the switch to enforcement.

Why adoption matters now

Google has been pushing Trusted Types since 2019 and uses them internally on many of its own properties. Chrome ships full support. The specification is at the W3C candidate recommendation stage. As AI-generated code becomes more common on the web, the risk of unsanitized DOM sinks increases because AI code generators frequently use innerHTML for convenience.

If you are building web applications that handle user input, which is almost every web application, Trusted Types is the strongest available defense against DOM XSS. It is not a replacement for CSP. It is the complement that closes the gap CSP leaves open.

For anyone building client-facing tools and sites on lean budgets, as I cover in The $97 Launch, Trusted Types cost nothing to implement on a new project. Adding them to an existing codebase takes more work, which is exactly why the audit tool exists: to show you the scope before you commit.

Fact-check notes and sources

  • Trusted Types specification: W3C Candidate Recommendation. Source: w3.org/TR/trusted-types/.
  • Chrome shipped Trusted Types enforcement in Chrome 83 (May 2020). Source: Chrome Platform Status.
  • DOM XSS represents a significant portion of XSS vulnerabilities. Source: OWASP, "DOM Based XSS" documentation.
  • Google uses Trusted Types internally on properties including Gmail. Source: Google Security Blog, "Trusted Types help prevent Cross-Site Scripting" (2020).

Related reading

This post is informational, not security consulting advice. Mentions of Google and Chrome are nominative fair use. No affiliation is implied.

← Back to Blog

Accessibility Options

Text Size
High Contrast
Reduce Motion
Reading Guide
Link Highlighting
Accessibility Statement

J.A. Watte is committed to ensuring digital accessibility for people with disabilities. This site conforms to WCAG 2.1 and 2.2 Level AA guidelines.

Measures Taken

  • Semantic HTML with proper heading hierarchy
  • ARIA labels and roles for interactive components
  • Color contrast ratios meeting WCAG AA (4.5:1)
  • Full keyboard navigation support
  • Skip navigation link
  • Visible focus indicators (3:1 contrast)
  • 44px minimum touch/click targets
  • Dark/light theme with system preference detection
  • Responsive design for all devices
  • Reduced motion support (CSS + toggle)
  • Text size customization (14px–20px)
  • Print stylesheet

Feedback

Contact: jwatte.com/contact

Full Accessibility StatementPrivacy Policy

Last updated: April 2026