Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten. Erfahre mehr über dieses Experiment.

View in English Always switch to English

ShadowRoot: Methode setHTMLUnsafe()

Baseline 2025
Neu verfügbar
*

Seit September 2025 funktioniert diese Funktion auf aktuellen Geräten und in aktuellen Browserversionen. Auf älteren Geräten oder in älteren Browsern funktioniert sie möglicherweise nicht.

Want more browser support for this feature? Tell us why.

* Einige Teile dieser Funktion werden möglicherweise unterschiedlich gut unterstützt.

Warnung: Diese Methode parst ihre Eingabe als HTML und schreibt das Ergebnis in das DOM. APIs wie diese gelten als Injektionssenken und können ein Angriffsweg für Cross-Site-Scripting-Angriffe (XSS) sein, wenn die Eingabe ursprünglich von einem Angreifer stammt.

Sie können dieses Risiko verringern, indem Sie immer TrustedHTML-Objekte statt Zeichenfolgen übergeben und Trusted Types durchsetzen. Weitere Informationen finden Sie unter Sicherheitsaspekte.

Hinweis: Sofern vom Browser unterstützt, sollte fast immer ShadowRoot.setHTML() statt dieser Methode verwendet werden, da sie stets XSS-unsichere HTML-Elemente und -Attribute entfernt.

Die Methode setHTMLUnsafe() der Schnittstelle ShadowRoot kann HTML-Eingaben in ein DocumentFragment parsen, dabei optional unerwünschte Elemente und Attribute herausfiltern und anschließend den bestehenden Baum im Shadow DOM durch das Ergebnis ersetzen.

Syntax

js
setHTMLUnsafe(input)
setHTMLUnsafe(input, options)

Parameter

input

Eine TrustedHTML-Instanz oder eine Zeichenfolge mit dem zu parsenden HTML.

options Optional

Ein Optionsobjekt mit dem folgenden optionalen Parameter:

sanitizer Optional

Ein Sanitizer- oder SanitizerConfig-Objekt, das festlegt, welche Elemente der Eingabe zugelassen oder entfernt werden. Alternativ kann dies eine Zeichenfolge mit dem Wert "default" sein. Dadurch wird ein Sanitizer mit der (XSS-sicheren) Standard-Sanitizer-Konfiguration angewendet. Wenn der Parameter nicht angegeben wird, wird kein Sanitizer verwendet.

Wenn Sie dieselbe Konfiguration mehrfach verwenden, ist es voraussichtlich effizienter, einen Sanitizer zu verwenden und ihn bei Bedarf anzupassen.

Rückgabewert

Keiner (undefined).

Ausnahmen

TypeError

Wird in folgenden Fällen ausgelöst:

  • Für input wird eine Zeichenfolge übergeben, während Trusted Types durch eine CSP erzwungen werden und keine Standardrichtlinie definiert ist.
  • Für options.sanitizer wird Folgendes übergeben:
    • Eine SanitizerConfig, die nicht gültig ist. Ein Beispiel ist eine Konfiguration, die sowohl Einstellungen für zugelassene als auch für entfernte Elemente enthält.
    • Eine Zeichenfolge mit einem anderen Wert als "default".
    • Ein Wert, der weder ein Sanitizer noch eine SanitizerConfig oder eine Zeichenfolge ist.

Beschreibung

Die Methode setHTMLUnsafe() kann eine HTML-Zeichenfolge parsen, dabei optional unerwünschte Elemente und Attribute herausfiltern und anschließend das bestehende Shadow DOM durch das Ergebnis ersetzen.

Anders als bei ShadowRoot.innerHTML werden deklarative Shadow Roots in der Eingabe in das DOM geparst. Wenn die HTML-Zeichenfolge für einen bestimmten Shadow-Host mehr als einen deklarativen Shadow Root definiert, wird nur der erste ShadowRoot erstellt. Nachfolgende Deklarationen werden als <template>-Elemente innerhalb dieses Shadow Roots geparst.

setHTMLUnsafe() führt standardmäßig keine Bereinigung durch. Wenn kein Sanitizer als Parameter übergeben wird, werden sämtliche HTML-Elemente und -Attribute der Eingabe eingefügt.

Sicherheitsaspekte

Der Namenszusatz „Unsafe“ weist darauf hin, dass die Methode – anders als ShadowRoot.setHTML() – nicht die Entfernung aller XSS-unsicheren HTML-Elemente und -Attribute erzwingt. Mit einem geeigneten Sanitizer kann sie diese zwar entfernen, sie muss aber weder einen wirksamen Sanitizer noch überhaupt einen Sanitizer verwenden. Die Methode kann daher ein Angriffsweg für Cross-Site Scripting (XSS) sein, wenn potenziell unsichere Zeichenfolgen von Benutzern ohne vorherige Bereinigung in das DOM eingefügt werden.

Sie sollten dieses Risiko verringern, indem Sie immer TrustedHTML-Objekte statt Zeichenfolgen übergeben und Trusted Types mit der CSP-Direktive require-trusted-types-for durchsetzen. So wird sichergestellt, dass die Eingabe eine Transformationsfunktion durchläuft, die sie vor dem Einfügen bereinigen und potenziell gefährliches Markup entfernen kann, etwa <script>-Elemente und Event-Handler-Attribute.

Durch die Verwendung von TrustedHTML können Sie an wenigen Stellen prüfen, ob der Bereinigungscode wirksam ist, statt dies bei allen Injektionssenken einzeln tun zu müssen. Wenn Sie TrustedHTML verwenden, sollten Sie der Methode keinen Sanitizer übergeben müssen.

Falls Sie aus irgendeinem Grund weder TrustedHTML noch – die bessere Wahl – setHTML() verwenden können, ist die nächstsicherste Option, setHTMLUnsafe() mit der XSS-sicheren Standard-Sanitizer-Konfiguration zu verwenden.

Wann sollte setHTMLUnsafe() verwendet werden?

Wenn ShadowRoot.setHTML() verfügbar ist, sollte setHTMLUnsafe() fast nie verwendet werden: Es gibt kaum Fälle, in denen von Benutzern bereitgestellte HTML-Eingaben XSS-unsichere Elemente enthalten müssen. setHTML() ist nicht nur sicher, sondern erspart Ihnen auch die Auseinandersetzung mit Trusted Types.

Die Verwendung von setHTMLUnsafe() kann sinnvoll sein, wenn:

  • Sie weder setHTML() noch Trusted Types verwenden können und die Eingabe möglichst sicher filtern möchten. In diesem Fall können Sie setHTMLUnsafe() mit der Standard-Sanitizer-Konfiguration verwenden, um XSS-unsichere und andere problematische Elemente herauszufiltern.

  • Sie setHTML() nicht verwenden können und die Eingabe deklarative Shadow Roots enthalten könnte, sodass auch ShadowRoot.innerHTML nicht infrage kommt.

  • Sie in einem Sonderfall HTML-Eingaben zulassen müssen, die eine bekannte Gruppe unsicherer HTML-Elemente und -Attribute enthalten.

    setHTML() können Sie in diesem Fall nicht verwenden, da es alle unsicheren Elemente und Attribute entfernt. Sie könnten setHTMLUnsafe() ohne Sanitizer oder innerHTML verwenden, würden damit aber alle unsicheren Elemente und Attribute zulassen.

    Besser ist es, setHTMLUnsafe() mit einem Sanitizer aufzurufen, der nur die tatsächlich benötigten gefährlichen Elemente und Attribute zulässt. Das bleibt zwar unsicher, ist aber sicherer, als alle zuzulassen.

Betrachten Sie für den letzten Fall eine Situation, in der Ihr Code auf die Verwendung unsicherer onclick-Handler angewiesen ist. Der folgende Code zeigt, wie sich die verschiedenen Methoden und Sanitizer in diesem Fall auswirken.

js
const shadow = document.querySelector("#host").shadowRoot;

const input = "<img src=x onclick=alert('onclick') onerror=alert('onerror')>";

// Safe - removes all XSS-unsafe entities.
shadow.setHTML(input);

// Removes no event handler attributes
shadow.setHTMLUnsafe(input);
shadow.innerHTML = input;

// Safe - removes all XSS-unsafe entities.
const configSafe = new Sanitizer();
shadow.setHTMLUnsafe(input, { sanitizer: configSafe });

// Removes all XSS-unsafe entities except `onclick`
const configLessSafe = new Sanitizer();
config.allowAttribute("onclick");
shadow.setHTMLUnsafe(input, { sanitizer: configLessSafe });

Beispiele

setHTMLUnsafe() mit Trusted Types

Um das XSS-Risiko zu verringern, erstellen wir zunächst aus der HTML-Zeichenfolge ein TrustedHTML-Objekt und übergeben dieses dann an setHTMLUnsafe(). Da Trusted Types noch nicht von allen Browsern unterstützt werden, definieren wir den Trusted-Types-Tinyfill. Er dient als transparenter Ersatz für die Trusted Types JavaScript API:

js
if (typeof trustedTypes === "undefined")
  trustedTypes = { createPolicy: (n, rules) => rules };

Als Nächstes erstellen wir eine TrustedTypePolicy, die eine createHTML()-Methode definiert, um eine Eingabezeichenfolge in TrustedHTML-Instanzen umzuwandeln. Implementierungen von createHTML() verwenden häufig eine Bibliothek wie DOMPurify, um die Eingabe wie unten gezeigt zu bereinigen:

js
const policy = trustedTypes.createPolicy("my-policy", {
  createHTML: (input) => DOMPurify.sanitize(input),
});

Anschließend verwenden wir dieses policy-Objekt, um aus der potenziell unsicheren Eingabezeichenfolge ein TrustedHTML-Objekt zu erstellen:

js
// The potentially malicious string
const untrustedString = "abc <script>alert(1)<" + "/script> def";
// Create a TrustedHTML instance using the policy
const trustedHTML = policy.createHTML(untrustedString);

Nachdem wir trustedHTML erstellt haben, zeigt der folgende Code, wie Sie es mit setHTMLUnsafe() verwenden können. Zunächst erstellen wir den ShadowRoot, den wir bearbeiten möchten. Er könnte programmgesteuert mit Element.attachShadow() erstellt werden; für dieses Beispiel erstellen wir ihn jedoch deklarativ.

html
<div id="host">
  <template shadowrootmode="open">
    <span>A span element in the shadow DOM</span>
  </template>
</div>

Dann greifen wir über das Element #host auf den Shadow Root zu und rufen setHTMLUnsafe() auf. Die Eingabe hat die Transformationsfunktion bereits durchlaufen, daher übergeben wir der Methode keinen Sanitizer.

js
const shadow = document.querySelector("#host").shadowRoot;
// setHTMLUnsafe() with no sanitizer (no filtering)
shadow.setHTMLUnsafe(trustedHTML);

setHTMLUnsafe() ohne Trusted Types verwenden

Dieses Beispiel zeigt den Fall, dass wir keine Trusted Types verwenden und daher Sanitizer-Argumente übergeben.

Der Code erstellt zunächst eine nicht vertrauenswürdige Zeichenfolge und zeigt verschiedene Möglichkeiten, der Methode einen Sanitizer zu übergeben.

js
// The potentially malicious string
const untrustedString = "abc <script>alert(1)<" + "/script> def";

// Get the shadow root element
const shadow = document.querySelector("#host").shadowRoot;

// Define custom Sanitizer and use in setHTMLUnsafe()
// This allows only elements: div, p, button, script
const sanitizer1 = new Sanitizer({
  elements: ["div", "p", "button", "script"],
});
shadow.setHTMLUnsafe(untrustedString, { sanitizer: sanitizer1 });

// Define custom SanitizerConfig within setHTMLUnsafe()
// Removes the <script> element but allows other potentially unsafe entities.
shadow.setHTMLUnsafe(untrustedString, {
  sanitizer: { removeElements: ["script"] },
});

Interaktives Beispiel für setHTMLUnsafe()

Dieses Beispiel zeigt eine interaktive Demonstration der Methode mit verschiedenen Sanitizern. Der Code definiert Schaltflächen, mit denen Sie eine HTML-Zeichenfolge einfügen können. Eine Schaltfläche fügt das HTML ohne jegliche Bereinigung ein. Die zweite verwendet einen benutzerdefinierten Sanitizer, der <script>-Elemente zulässt, andere unsichere Bestandteile jedoch nicht. Die ursprüngliche Zeichenfolge und das eingefügte HTML werden protokolliert, damit Sie die Ergebnisse in beiden Fällen prüfen können.

Hinweis: Da wir zeigen möchten, wie das Sanitizer-Argument verwendet wird, fügt der folgende Code eine Zeichenfolge statt eines Trusted Type ein. In Produktionscode sollten Sie dies nicht tun.

HTML

Das HTML definiert zwei <button>-Elemente, um das HTML ohne Sanitizer beziehungsweise mit einem benutzerdefinierten Sanitizer einzufügen, eine weitere Schaltfläche zum Zurücksetzen des Beispiels sowie ein <div>, das den deklarativen Shadow Root enthält.

html
<button id="buttonNoSanitizer" type="button">None</button>
<button id="buttonAllowScript" type="button">allowScript</button>
<button id="reload" type="button">Reload</button>

<div id="host">
  <template shadowrootmode="open">
    <span>I am in the shadow DOM </span>
  </template>
</div>

JavaScript

Zunächst definieren wir den Handler für die Schaltfläche zum Neuladen.

js
const reload = document.querySelector("#reload");
reload.addEventListener("click", () => document.location.reload());

Dann definieren wir die Eingabezeichenfolge, die in den Shadow Root eingefügt werden soll und in allen Fällen gleich ist. Sie enthält das <script>-Element und den onclick-Handler, die beide als XSS-unsicher gelten. Außerdem holen wir die Variable shadow, über die wir auf den Shadow Root zugreifen.

js
// Define unsafe string of HTML
const unsanitizedString = `
  <div>
    <p>Paragraph to inject into shadow DOM.
      <button onclick="alert('You clicked the button!')">Click me</button>
    </p>
    <script src="path/to/a/module.js" type="module"><\/script>
    <p data-id="123">Para with <code>data-</code> attribute</p>
  </div>
`;

const shadow = document.querySelector("#host").shadowRoot;

Als Nächstes definieren wir den Klick-Handler für die Schaltfläche, die den Shadow Root mit setHTMLUnsafe() setzt, ohne einen Sanitizer zu übergeben. Da kein Sanitizer verwendet wird, erwarten wir, dass das eingefügte HTML mit der Eingabezeichenfolge übereinstimmt.

js
const buttonNoSanitizer = document.querySelector("#buttonNoSanitizer");
buttonNoSanitizer.addEventListener("click", () => {
  // Set the content of the element with no sanitizer
  shadow.setHTMLUnsafe(unsanitizedString);

  // Log HTML before sanitization and after being injected
  logElement.textContent = "No sanitizer\n\n";
  log(`\nunsanitized: ${unsanitizedString}`);
  log(`\n\nsanitized: ${shadow.innerHTML}`);
});

Der nächste Klick-Handler setzt das Ziel-HTML mit einem benutzerdefinierten Sanitizer, der nur die Elemente <div>, <p> und <script> zulässt.

js
const allowScriptButton = document.querySelector("#buttonAllowScript");
allowScriptButton.addEventListener("click", () => {
  // Set the content of the element using a custom sanitizer
  const sanitizer1 = new Sanitizer({
    elements: ["div", "p", "script"],
  });
  shadow.setHTMLUnsafe(unsanitizedString, { sanitizer: sanitizer1 });

  // Log HTML before sanitization and after being injected
  logElement.textContent = "Sanitizer: {elements: ['div', 'p', 'script']}\n";
  log(`\n\nunsanitized: ${unsanitizedString}`);
  log(`\nsanitized: ${shadow.innerHTML}`);
});

Ergebnisse

Klicken Sie auf die Schaltflächen „None“ und „allowScript“, um zu sehen, wie sich das Fehlen eines Sanitizers beziehungsweise ein benutzerdefinierter Sanitizer auswirkt.

Wenn Sie auf „None“ klicken, sollten Eingabe und Ausgabe übereinstimmen, da kein Sanitizer angewendet wird. Wenn Sie auf „allowScript“ klicken, bleibt das <script>-Element erhalten, das <button>-Element wird jedoch entfernt. Mit diesem Ansatz können Sie sicheres HTML erzeugen, sind dazu aber nicht gezwungen.

Spezifikationen

Spezifikation
HTML
# dom-shadowroot-sethtmlunsafe

Browser-Kompatibilität

Siehe auch