【実務・中級編】JavaScriptのinnerHTMLとtextContentのセキュリティ特性比較 – アプリケーションセキュリティ & 安全な開発防御ガイド

なぜ、その「innerHTML」があなたのシステムを沈没させるのか?

現場でコードレビューをしていると、未だに「とりあえずこれで動くから」と innerHTML を多用しているエンジニアによく出会う。正直に言おう。そのコードは、あなたのアプリケーションに対する「裏口」を常に開けっ放しにしているのと同じだ。

今回は、Webフロントエンドにおいて最も基本的でありながら、最も軽視されがちな「DOM操作のセキュリティ」について、現場の泥臭い知見を交えて解説する。

—

1. innerHTMLの「悪魔の誘惑」とその正体

innerHTML は、文字列をHTMLとしてパースし、DOMツリーに展開する。開発者にとっては、動的にUIを構築できる便利なツールだ。しかし、この「HTMLとしてパースする」という性質こそが、攻撃者にとっての格好の入り口になる。

攻撃者が見ている「盲点」:PoCで理解する

例えば、ユーザーが入力した「名前」を画面に表示するだけの機能で、innerHTML を使ってしまったとしよう。

// 脆弱な実装
const userInput = ““;
document.getElementById(‘display’).innerHTML = “こんにちは、” + userInput;

攻撃者が userInput に上記のような細工をした文字列を送り込むと、ブラウザは「imgタグの読み込み失敗」をトリガーにして、onerror 属性内の悪意あるJavaScriptを実行する。

これがXSS(クロスサイトスクリプティング)の基本形だ。もしこれが alert ではなく、「セッションIDを外部の攻撃者サーバーに送信するスクリプト」だったらどうなるか? 想像するだけで背筋が凍るはずだ。WAFをすり抜ける難読化手法などは後を絶たない。根本的な防御は「ブラウザにHTMLとして解釈させないこと」に尽きる。

—

2. textContentという最強の盾

一方で textContent は、その名の通り「テキスト」としてのみ扱う。たとえ入力値の中に ";
const displayElement = document.getElementById('display');

// これならタグは実行されず、文字列としてそのまま表示される
displayElement.textContent = userInput;

ケースB:HTMLタグを一部許可したい場合

どうしてもHTMLをレンダリングする必要があるなら、必ずライブラリを通せ。車輪の再発明はするな。

// npm install dompurify
import DOMPurify from 'dompurify';

const unsafeHTML = "こんにちは";

// DOMPurifyが危険な属性やタグを除去し、安全なHTMLのみを返す
const cleanHTML = DOMPurify.sanitize(unsafeHTML);

document.getElementById('display').innerHTML = cleanHTML;

---

4. インフラ・バックエンド側の二段構え

フロントエンドでの対策に加え、サーバー側でも「防御の深層(Defense in Depth)」を意識した設定を忘れてはならない。

CSP(Content Security Policy)でトドメを刺す

万が一、コードに脆弱性が残っていたとしても、CSPを設定していれば被害を最小限に抑えられる。Nginxの設定例を挙げておく。

Nginx設定例:信頼できないソースからのスクリプト実行を禁止する
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none';";

  • default-src 'self' : コンテンツは自分のドメインからのみ読み込む。
  • script-src 'self' : インラインスクリプト(innerHTML経由の攻撃含む)の実行を原則禁止する。

---

最後に:プロフェッショナルとしての心得

「動けばいい」というコードは、数ヶ月後の自分やチームメンバーに技術的負債という名の爆弾を手渡す行為だ。

今回紹介した textContent への切り替えは、単なる修正ではない。「ブラウザの解釈に委ねるな、明示的に制御せよ」というセキュリティの基本原則を実践するということだ。

もし今日、あなたのプロジェクトのソースコードを検索して innerHTML が見つかったら、それは「改善のチャンス」だ。今すぐリファクタリングのタスクをチケットに起票してほしい。それができるチームこそが、真に信頼されるエンジニア集団であると私は信じている。

コメント

タイトルとURLをコピーしました