v146 · Security · DOM API

Sanitizer API

Chrome 146 ships the Sanitizer API — a safe-by-default, browser-native way to inject untrusted HTML into the DOM without executing scripts or attaching event handlers. Element.setHTML() parses and sanitizes in one step, removing <script> tags, onerror attributes, and any markup that could lead to XSS. A configurable Sanitizer object lets you further restrict the allowed element and attribute set.

concepts

  1. XSS Sanitizer Demo

    Paste or type untrusted HTML. See how the default Sanitizer strips <script>, inline event handlers (onerror, onclick), javascript: hrefs, and other dangerous constructs — while preserving safe markup like <b>, <p>, and links.

  2. Custom Sanitizer Config

    Build a custom Sanitizer by specifying allowed elements and attributes. Useful for user-comment fields (allow bold and links only), rich-text editors (allow headings and lists), or plain-text-only inputs (allow nothing).

  3. Policy comparator

    Three lanes (default, strict, custom) running the same input through setHTML(). Paste hostile markup, edit the custom config JSON, and watch the rendered output, the resulting HTML and the elements/attributes removed.

  4. Comment Editor

    A rich comment editor with a live sanitized preview. Type or paste HTML — including XSS payloads — and the preview renders safe output via element.setHTML() while a threat log tracks every element and attribute the sanitizer removed.

why it shipped

Injecting user-generated HTML into a page — for comments, previews, copy-paste — is one of the most common sources of XSS vulnerabilities. The standard pattern, innerHTML = userHTML, gives attackers full DOM control. Libraries like DOMPurify fill the gap but are large, complex, and must be kept up-to-date as the HTML spec evolves. The Sanitizer API moves this responsibility into the browser: it knows the full set of dangerous attributes and elements for the current HTML version, removes them by default, and runs before the HTML is inserted — so there is no race between parsing and sanitization. The Sanitizer configuration object lets you restrict even further, down to a plain-text-only policy if needed.

the API

// Basic use: default sanitizer blocks scripts, event handlers, etc.
const div = document.getElementById('output');
div.setHTML(userSuppliedHTML);
// <script>alert(1)</script> → removed
// <img onerror="xss()"> → onerror attribute removed
// <a href="javascript:xss()"> → href sanitized

// setHTMLUnsafe() — NO sanitization. Only use for fully-trusted HTML.
div.setHTMLUnsafe(trustedHTML);

// Custom configuration: restrict to a specific allow-list
const sanitizer = new Sanitizer({
  elements: ['b', 'i', 'em', 'strong', 'a', 'p', 'br'],
  attributes: { 'href': ['a'] },
});
div.setHTML(commentHTML, { sanitizer });

// Even more restrictive: no elements at all (plain text)
const textOnly = new Sanitizer({ elements: [] });
span.setHTML(input, { sanitizer: textOnly }); // only text nodes survive

references