How to Configure Strict Trusted Types for DOM XSS Enforcement in Google Chrome

DOM-based Cross-Site Scripting (DOM XSS) remains one of the most pervasive client-side vulnerabilities in modern single-page applications. It occurs when untrusted user input reaches dangerous browser execution sinks—such as element.innerHTML, document.write(), or location.href. While traditional Content Security Policy (CSP) restricts network origins, it cannot distinguish between safe and tainted JavaScript strings passed into DOM sinks. Trusted Types enforces a strict type system at the browser engine level, requiring all sink inputs to be validated and wrapped into typed objects before Chrome permits execution.

Understanding Trusted Types and DOM Injection Sinks

When Trusted Types is enabled, Google Chrome locks down hazardous injection sinks. Attempting to assign a plain string to innerHTML immediately throws a runtime TypeError. Instead, applications must generate values through approved policy factories that yield:

  • TrustedHTML: For markup manipulation sinks like innerHTML and outerHTML.
  • TrustedScript: For script execution sinks like eval() and new Function().
  • TrustedScriptURL: For dynamic script loading sinks like script.src and worker.constructor.

Enforcing Trusted Types via Content Security Policy

To mandate Trusted Types across your web application, issue the require-trusted-types-for directive from your web server:

# Nginx CSP header enforcing Trusted Types
add_header Content-Security-Policy "require-trusted-types-for 'script'; trusted-types default dompurify-policy;" always;

# Apache HTTP Server (.htaccess / virtual host)
Header always set Content-Security-Policy "require-trusted-types-for 'script'; trusted-types default dompurify-policy;"

The trusted-types token specifies the explicit policy names allowed to create trusted objects, preventing rogue third-party libraries from registering unvetted sanitisation factories.

Authoring a Trusted Types Sanitisation Policy in JavaScript

Implement an application-wide policy leveraging a hardened sanitiser such as DOMPurify:

// Ensure browser supports Trusted Types
if (window.trustedTypes && window.trustedTypes.createPolicy) {
    const sanitizePolicy = window.trustedTypes.createPolicy('dompurify-policy', {
        createHTML: (string) => DOMPurify.sanitize(string, { RETURN_TRUSTED_TYPE: false }),
        createScriptURL: (string) => {
            const url = new URL(string, window.location.origin);
            if (url.origin === window.location.origin && url.pathname.startsWith('/static/js/')) {
                return url.href;
            }
            throw new TypeError('Untrusted script URL source blocked: ' + string);
        }
    });

    // Safely assign validated HTML to DOM sinks
    const userComment = "<img src=x onerror=alert(1)>Hello World";
    const cleanHtml = sanitizePolicy.createHTML(userComment);
    document.getElementById('content-area').innerHTML = cleanHtml;
}

Auditing Trusted Types Violations in Chrome DevTools

To inspect and debug Trusted Types compliance in Google Chrome:

  1. Open Google Chrome and navigate to the application.
  2. Press Ctrl + Shift + I (or Option + Command + I on macOS) to open Chrome DevTools.
  3. Switch to the Console tab. If any script passes an unvetted string to an injection sink, Chrome halts execution with an explicit violation error:
    Uncaught TypeError: Failed to set the 'innerHTML' property on 'Element': This document requires 'TrustedHTML' assignment.
  4. Open the Sources tab, expand the XHR/fetch and DOM Breakpoints pane, and check Trusted Type Violations. Chrome automatically pauses execution on the exact line of JavaScript attempting the unapproved assignment.
  5. Inspect the Issues tab to review recommendations for migrating legacy DOM sink calls.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.