setHTMLUnsafe について:setHTML / parseHTMLUnsafe

setHTMLUnsafe は HTML 文字列を要素に挿入するメソッドです。名前に「Unsafe」とあるとおり、サニタイズ処理を行わずに HTML をそのまま解釈します。

基本的な使い方

const div = document.getElementById('container')
div.setHTMLUnsafe('<b>太字</b><script>alert("実行される")</script>')

innerHTML と同様に、渡された文字列は HTML として解釈されます。<script> タグも実行されるため、信頼できない入力を渡すと XSS 脆弱性につながります。

innerHTML との違い

setHTMLUnsafe は Declarative Shadow DOM を含む HTML 文字列を処理できます。

const html = `
  <div>
    <template shadowrootmode="open">
      <style>p { color: red; }</style>
      <p>Shadow DOM 内のコンテンツ</p>
    </template>
  </div>
`

document.body.setHTMLUnsafe(html)
// → Shadow DOM が正しく構築される

document.body.innerHTML = html
// → template 要素がそのまま残り、Shadow DOM は構築されない

innerHTML<template shadowrootmode="..."> を通常の template 要素として扱いますが、setHTMLUnsafe は Declarative Shadow DOM として解釈し、Shadow Root を構築します。

setHTML との関係

setHTML はサニタイズ処理を行う安全なメソッドです。setHTMLUnsafe はその「安全装置を外した」バージョンという位置づけです。

const dirty = '<img src=x onerror=alert(1)><b>太字</b>'

// setHTML: 危険な要素を除去
div.setHTML(dirty)
// → <b>太字</b> のみ挿入

// setHTMLUnsafe: そのまま挿入
div.setHTMLUnsafe(dirty)
// → img タグも挿入され、onerror が発火する可能性あり

parseHTMLUnsafe

静的メソッド Document.parseHTMLUnsafe を使うと、HTML 文字列から Document オブジェクトを生成できます。

const doc = Document.parseHTMLUnsafe(`
  <!DOCTYPE html>
  <html>
    <head><title>Test</title></head>
    <body><p>内容</p></body>
  </html>
`)

doc.querySelector('p').textContent  // → '内容'

こちらも Declarative Shadow DOM を含む HTML を正しく解釈します。

使用場面

setHTMLUnsafe は信頼できるソースからの HTML を扱う場合に限定して使います。サーバーサイドレンダリングで生成した Declarative Shadow DOM を含む HTML を挿入する場合などが典型的なユースケースです。ユーザー入力を含む文字列には決して使わないでください。