innerHTMLは危険
フロントエンド開発では、HTML文字列をDOMへ挿入する場面がよくあります。
しかし、innerHTML を安易に使うとXSS(クロスサイトスクリプティング)の温床になります。
XSSとは、Webサイトに悪意のあるスクリプトを仕込み、閲覧したユーザーのブラウザ上で実行させるサイバー攻撃またはその脆弱性のことです。
innerHTMLは文字列をそのままHTMLとして解釈するので、以下のようなコードだとonerrorが実行されて、XSSが成立します。
const h1 = document.querySelector('h1')
h1.innerHTML = 'TEST:<img src=x onerror=alert(1)>'
// <h1>TEST:<img src=x onerror=alert(1)></h1> になって危険setHTMLは安全
安全にHTMLを挿入するには、前述のimgタグのonerrorなどの危険なコードを取り除く必要があります。
innerHTMLの代わりにsetHTMLを使用すれば、onerrorなどの危険なコードを取り除いた状態でHTMLのコードを要素に挿入できるので安全です。
const h1 = document.querySelector('h1')
h1.setHTML('TEST:<img src=x onerror=alert(1)>')
// <h1>TEST:<img src=x></h1> になって安全ここまでで、HTMLを挿入する際はinnerHTMLよりsetHTMLを使用したほうが良いことはわかりましたが、1つ問題があります。
それは使用できるブラウザが少ないことです。
Chromeで使用可能なバージョンは146からですが、2026年2月27日現在のバージョンは145のため使えません。
Microsoft EdgeやSafariに関しては対応されるバージョンすら未定です。
しかし、次項で説明するsetHTMLが使用できない場合はDOMPurifyで安全なコードにして挿入する方法を使用すれば、setHTMLを全ブラウザで使用可能になります。
全ブラウザ対応の安全なsetHTML実装
以下はsetHTMLが使用できない場合はDOMPurifyを使用して、安全にHTMLを挿入するコードです。
DOMPurifyとはXSS対策のためのサニタイズライブラリです。
ユーザー入力や外部HTMLを安全にDOMへ挿入できるように、危険なタグや属性を除去してくれます。
DOMPurifyは「npm i dompurify」でインストールしてから使用します。
import DOMPurify from 'dompurify'
if (!Element.prototype.setHTML) {
Object.defineProperty(Element.prototype, 'setHTML', {
configurable: true,
writable: true,
value: function setHTML(html) {
const input = String(html ?? '')
const config = {
USE_PROFILES: { html: true },
}
const sanitized = DOMPurify.sanitize(input, config)
this.innerHTML = sanitized
},
})
}
const h1 = document.querySelector('h1')
h1.setHTML('TEST:<img src=x onerror=alert(1)>')
// <h1>TEST:<img src=x></h1>npmを使用していない環境で、HTMLファイル内のscriptタグ内に直接コードが書かれている場合は <script type="module"> に変更し、DOMPurifyをURLからimportして使用してください。
<h1></h1>
<script type="module">
import DOMPurify from 'https://cdn.jsdelivr.net/npm/dompurify/dist/purify.es.mjs'
if (!Element.prototype.setHTML) {
Object.defineProperty(Element.prototype, 'setHTML', {
configurable: true,
writable: true,
value: function setHTML(html) {
const input = String(html ?? '')
const config = {
USE_PROFILES: { html: true },
}
const sanitized = DOMPurify.sanitize(input, config)
this.innerHTML = sanitized
},
})
}
const h1 = document.querySelector('h1')
h1.setHTML('TEST:<img src=x onerror=alert(1)>')
// <h1>TEST:<img src=x></h1>
</script>まとめ
innerHTMLはWeb開発ではXSSの危険性があるので使うべきではありません。
特定の要素内にHTMLコードを挿入する必要がある場合は、前述の全ブラウザ対応のsetHTMLを使うことを推奨します。



