innerHTML よりも安全?な関数:insertAdjacentText / setHTML
innerHTML は文字列を HTML として解釈するため、ユーザー入力をそのまま渡すと XSS 脆弱性の原因になります。より安全な代替手段を紹介します。
textContent
テキストのみを扱う場合は textContent を使います。HTML として解釈されないため、悪意のあるスクリプトが実行されることはありません。
const div = document.getElementById('output')
div.textContent = '<script>alert("XSS")</script>'
// → 文字列がそのまま表示され、スクリプトは実行されないDOM 操作メソッド
要素を動的に構築する場合は、createElement と appendChild を組み合わせます。
const ul = document.getElementById('list')
const items = ['<b>Apple</b>', 'Banana', 'Cherry']
items.forEach(item => {
const li = document.createElement('li')
li.textContent = item // HTML として解釈されない
ul.appendChild(li)
})この方法では各要素を個別に作成するため、構造が明確になり、意図しない HTML の混入を防げます。
insertAdjacentText
特定の位置にテキストを挿入する場合は insertAdjacentText が便利です。insertAdjacentHTML と異なり、文字列を HTML として解釈しません。
const div = document.getElementById('container')
div.insertAdjacentText('beforeend', '<script>危険</script>')
// → テキストとして安全に挿入されるsetHTMLUnsafe と Sanitizer API
信頼できない HTML を扱う必要がある場合、Sanitizer API を検討します。危険なタグや属性を除去してから DOM に挿入できます。
const dirty = '<img src=x onerror=alert("XSS")><b>太字</b>'
const sanitizer = new Sanitizer()
document.getElementById('output').setHTML(dirty, { sanitizer })
// → <b>太字</b> のみが挿入され、img タグは除去されるSanitizer API は比較的新しい機能のため、ブラウザの対応状況を確認してください。対応していない環境では DOMPurify などのライブラリで代用できます。
template 要素と cloneNode
複雑な構造を繰り返し生成する場合は <template> 要素を活用します。
<template id="card-template">
<div class="card">
<h2 class="title"></h2>
<p class="body"></p>
</div>
</template>const template = document.getElementById('card-template')
const clone = template.content.cloneNode(true)
clone.querySelector('.title').textContent = userInput.title
clone.querySelector('.body').textContent = userInput.body
document.body.appendChild(clone)テンプレートの構造は固定され、動的な値は textContent で安全に挿入されます。



