Start · Sprachen · JavaScript · Referenz · TrustedHTML

TrustedHTML

Schnittstelle

Repräsentiert einen von einer Trusted-Types-Policy geprüften String, der sicher in HTML-Injection-Senken wie <code>innerHTML</code> eingefügt werden darf.

seit JavaScript Chrome/Edge 83+, Firefox 133+ (hinter Flag bzw. ab Kategorie: webapi

Signatur

interface TrustedHTML

Beschreibung

TrustedHTML gehört zur Trusted Types API, mit der sich DOM-basiertes Cross-Site-Scripting (XSS) verhindern lässt. Ein TrustedHTML-Objekt kapselt einen String, der zuvor eine selbst definierte Bereinigungsfunktion einer TrustedTypePolicy durchlaufen hat. Nur solche Objekte akzeptiert der Browser dann in gefährlichen „Injection-Senken“ wie Element.innerHTML, Element.outerHTML, insertAdjacentHTML(), document.write(), DOMParser.parseFromString() oder iframe.srcdoc.

Einen eigenen Konstruktor gibt es nicht. Objekte entstehen ausschließlich über policy.createHTML(input), wobei die Policy vorher mit trustedTypes.createPolicy(name, { createHTML }) angelegt wird. Wird die CSP-Direktive require-trusted-types-for 'script' gesetzt, lösen einfache Strings in diesen Senken einen TypeError aus. So muss jeder HTML-Fluss durch eine prüfbare, zentrale Stelle laufen.

Die Schnittstelle ist bewusst schlank gehalten. Sie bietet nur toString() und toJSON(), die beide den gekapselten String zurückgeben. Ob ein Wert tatsächlich vertrauenswürdig ist, prüfst du mit trustedTypes.isHTML(value). Ein instanceof-Vergleich reicht nicht, weil er sich über Realm-Grenzen hinweg anders verhält.

Rückgabewert

Typ
TrustedHTML
Beschreibung
Wird von TrustedTypePolicy.prototype.createHTML() bzw. trustedTypes.emptyHTML geliefert. Instanzmethoden: toString() und toJSON() geben jeweils den bereinigten string zurück.

Beispiele

Policy anlegen und TrustedHTML erzeugen

// Einfache Escape-Policy: Sonderzeichen unschädlich machen
const escapePolicy = trustedTypes.createPolicy('escape-html', {
  createHTML: (input) => input
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
});

const userInput = '<img src=x onerror="alert(1)">';
const safe = escapePolicy.createHTML(userInput);

console.log(safe instanceof TrustedHTML);
console.log(trustedTypes.isHTML(safe));
document.querySelector('#kommentar').innerHTML = safe;
true true

Bereinigung mit DOMPurify als Policy

// Voraussetzung: DOMPurify ist geladen
const sanitizer = trustedTypes.createPolicy('dompurify', {
  createHTML: (dirty) => DOMPurify.sanitize(dirty)
});

const renderArticle = async (id) => {
  const res = await fetch(`/api/articles/${id}`);
  const { html } = await res.json();
  document.querySelector('main').innerHTML = sanitizer.createHTML(html);
};

renderArticle(42);

toString(), toJSON() und emptyHTML

const policy = trustedTypes.createPolicy('demo', {
  createHTML: (s) => s.trim()
});

const html = policy.createHTML('  <b>Hallo</b>  ');
console.log(html.toString());
console.log(JSON.stringify({ markup: html }));

// Leeren Inhalt ohne Policy setzen
document.body.innerHTML = trustedTypes.emptyHTML;
console.log(trustedTypes.isHTML(trustedTypes.emptyHTML));
<b>Hallo</b> {"markup":"<b>Hallo</b>"} true

Erzwingen per CSP und Feature-Erkennung

// HTTP-Header:
// Content-Security-Policy: require-trusted-types-for 'script'; trusted-types dompurify

const setHTML = (el, markup) => {
  if (window.trustedTypes?.createPolicy) {
    const p = trustedTypes.createPolicy('fallback', { createHTML: (s) => s });
    el.innerHTML = p.createHTML(markup);
  } else {
    el.innerHTML = markup; // Browser ohne Trusted Types
  }
};

try {
  document.body.innerHTML = '<p>roh</p>'; // bei aktiver CSP: TypeError
} catch (e) {
  console.log(e.name);
}
TypeError

// Wichtig · Fallstricke

  • Sicherheit: TrustedHTML ist nur so sicher wie die Funktion createHTML der Policy. Eine Policy wie (s) => s hebelt den Schutz vollständig aus. Setze deshalb auf bewährte Bereinigungsbibliotheken wie DOMPurify und halte die Zahl der Policies klein. Mit trusted-types <namen> in der CSP legst du fest, welche Policies erlaubt sind.
  • Ohne die CSP-Direktive require-trusted-types-for 'script' werden Trusted Types nicht erzwungen, und Strings funktionieren weiterhin. Mit Content-Security-Policy-Report-Only kannst du Verstöße zunächst nur melden lassen, statt sie zu blockieren.
  • Eine Policy namens "default" wird automatisch auf jeden rohen String angewendet, der in eine Senke gelangt. Das ist praktisch für die Umstellung bestehender Anwendungen, aber auch riskant.
  • Es gibt keinen öffentlichen Konstruktor: new TrustedHTML() wirft einen TypeError.
  • createPolicy() wirft einen Fehler, wenn der Name laut CSP nicht erlaubt ist oder doppelt vergeben wird (außer bei 'allow-duplicates').
  • Kompatibilität: Chromium-Browser unterstützen die API seit Version 83. Firefox und Safari haben sie erst kürzlich eingeführt. Prüfe die Unterstützung mit window.trustedTypes oder nutze den offiziellen Polyfill (trusted-types von W3C/Google). In Node.js gibt es die API nicht.