Start · Sprachen · JavaScript · Referenz · ShadowRoot.setHTMLUnsafe()

ShadowRoot.setHTMLUnsafe()

Methode

Parst einen HTML-String (inklusive deklarativem Shadow DOM) ohne automatische XSS-Bereinigung und ersetzt damit den gesamten Inhalt eines <code>ShadowRoot</code>.

seit JavaScript Baseline 2024 (Chrome 124, Firefox 123, Safari 17. Kategorie: webapi

Signatur

ShadowRoot.prototype.setHTMLUnsafe(input, options)

Beschreibung

setHTMLUnsafe() parst die übergebene HTML-Zeichenkette zu einem DocumentFragment, filtert optional anhand eines Sanitizers Elemente und Attribute heraus und ersetzt dann alle vorhandenen Kindknoten des Shadow Roots durch das Ergebnis. Funktional ähnelt die Methode dem Setzen von shadowRoot.innerHTML, bietet aber zwei wichtige Unterschiede.

Erstens wird deklaratives Shadow DOM ausgewertet: Enthält der HTML-Code ein <template shadowrootmode="open">, wird daraus ein echter Shadow Root am umgebenden Element erzeugt. Mit innerHTML bliebe dies ein gewöhnliches, inertes <template>. Das ist praktisch für Web Components, deren Markup verschachtelte Komponenten mit eigenem Shadow DOM enthält, etwa bei serverseitig gerendertem HTML.

Zweitens kann ein Sanitizer übergeben werden. Anders als bei setHTML() werden dabei aber nicht automatisch XSS-gefährliche Inhalte wie <script> oder onclick-Attribute entfernt. Entfernt wird nur, was die Sanitizer-Konfiguration ausdrücklich verbietet. Daher kommt das „Unsafe“ im Namen.

Benutzen Sie die Methode nur für vertrauenswürdiges Markup (eigene Templates, geprüfte Serverantworten) oder zusammen mit Trusted Types. Für Benutzereingaben und fremde Inhalte ist ShadowRoot.setHTML() die sichere Wahl.

Parameter

Name Typ Default Beschreibung
$input Pflicht string | TrustedHTML Das HTML, das geparst und in den Shadow Root eingefügt wird. Wenn Trusted Types per CSP erzwungen werden (require-trusted-types-for 'script'), muss ein TrustedHTML-Objekt übergeben werden.
$options object {} Optionales Konfigurationsobjekt.
$options.sanitizer Sanitizer | SanitizerConfig | "default" kein Filter Eine Sanitizer-Instanz, ein Konfigurationsobjekt (z. B. { elements: [...], removeAttributes: [...] }) oder "default". Ohne Angabe wird nichts gefiltert. Unsichere Elemente werden auch mit Sanitizer nur entfernt, wenn die Konfiguration das ausdrücklich verlangt. Diese Option wird noch nicht von allen Browsern unterstützt.

Rückgabewert

Typ
undefined
Beschreibung
Kein Rückgabewert. Der Inhalt des Shadow Roots wird direkt ersetzt.

Beispiele

Shadow-DOM-Inhalt einer Web Component setzen

class InfoCard extends HTMLElement {
  connectedCallback() {
    const root = this.attachShadow({ mode: 'open' });
    // Vertrauenswürdiges, eigenes Template
    root.setHTMLUnsafe(`
      <style>:host { display: block; border: 1px solid #ccc; padding: 1rem; }</style>
      <h2><slot name="titel">Ohne Titel</slot></h2>
      <slot></slot>
    `);
  }
}
customElements.define('info-card', InfoCard);

const card = document.createElement('info-card');
document.body.append(card);
console.log(card.shadowRoot.querySelector('h2') !== null);
true

Deklaratives Shadow DOM verschachtelter Elemente auswerten

const host = document.createElement('div');
const root = host.attachShadow({ mode: 'open' });

const markup = `
  <user-badge>
    <template shadowrootmode="open">
      <span part="name">Ada Lovelace</span>
    </template>
  </user-badge>`;

root.setHTMLUnsafe(markup);
const badge = root.querySelector('user-badge');
console.log(badge.shadowRoot?.querySelector('span').textContent);

// Zum Vergleich: innerHTML erzeugt keinen Shadow Root
root.innerHTML = markup;
console.log(root.querySelector('user-badge').shadowRoot);
Ada Lovelace null

Mit Sanitizer-Konfiguration bestimmte Elemente entfernen

const host = document.querySelector('#vorschau');
const root = host.shadowRoot ?? host.attachShadow({ mode: 'open' });

const html = '<p>Hallo <b>Welt</b></p><iframe src="https://example.com"></iframe>';

// Entfernt nur das, was in der Konfiguration steht, also hier <iframe>
root.setHTMLUnsafe(html, {
  sanitizer: { removeElements: ['iframe'] }
});

console.log(root.innerHTML);
<p>Hallo <b>Welt</b></p>

Zusammen mit Trusted Types verwenden

// Falls Trusted Types verfügbar ist, wird eine Policy angelegt
const policy = window.trustedTypes?.createPolicy('shadow-html', {
  createHTML: (s) => s.replace(/<script[\s\S]*?<\/script>/gi, '')
});

const host = document.createElement('section');
const root = host.attachShadow({ mode: 'open' });
const raw = '<p>Inhalt</p><script>alert(1)<\/script>';

root.setHTMLUnsafe(policy ? policy.createHTML(raw) : raw);
console.log(root.childElementCount);
1 (mit Trusted Types; ohne Policy würde das Script-Element mit eingefügt, aber nicht ausgeführt)

// Wichtig · Fallstricke

  • XSS-Gefahr: Die Methode bereinigt nicht automatisch. Event-Handler-Attribute wie onerror auf <img> werden ausgeführt, sobald das Element geladen wird. Geben Sie niemals ungeprüfte Benutzereingaben hinein. Nutzen Sie dafür setHTML().
  • Eingefügte <script>-Elemente werden wie bei innerHTML nicht ausgeführt. Andere Angriffswege (Inline-Handler, javascript:-URLs) funktionieren aber weiterhin.
  • Trusted Types / CSP: Ist require-trusted-types-for 'script' aktiv, löst eine normale Zeichenkette einen TypeError aus. Übergeben Sie dann ein TrustedHTML-Objekt.
  • Der gesamte bisherige Inhalt des Shadow Roots wird ersetzt. Event-Listener an alten Knoten gehen dabei verloren.
  • Kompatibilität: Die Methode selbst ist seit 2024 in allen großen Browsern verfügbar (Chrome/Edge 124, Firefox 123, Safari 17.4). Die Option sanitizer gehört zur neueren Sanitizer API und wird bisher nur eingeschränkt unterstützt. Browser ohne Unterstützung ignorieren die Option still, es wird dann also nichts gefiltert. Prüfen Sie die Verfügbarkeit, zum Beispiel mit 'Sanitizer' in window.
  • Die Methode gibt es auch als Element.prototype.setHTMLUnsafe() sowie als statische Methode Document.parseHTMLUnsafe().