Reactの「自動エスケープ」は銀の弾丸ではない:XSSを防ぐための正しい作法
現場でコードレビューをしていると、ReactがXSS(クロスサイトスクリプティング)に対して「どれだけ寛容で、どれだけ厳しいか」を誤解しているエンジニアによく出会います。
「Reactを使っていれば、とりあえずXSSは大丈夫でしょ?」
もし君がそう思っているなら、少しだけ立ち止まって耳を貸してほしい。Reactの自動エスケープは非常に優秀だが、それはあくまで「Reactの流儀に従った場合」の話に過ぎないんだ。今日は、Reactが裏側で何をやっているのか、そしてなぜ`dangerouslySetInnerHTML`という名前がわざわざ「危険」を冠しているのか、その深淵を覗いてみよう。
—
Reactがデフォルトで行う「魔法」の正体
ReactでJSXを書くとき、変数を `{data}` のように埋め込むはずだ。このとき、Reactは内部的に `textContent` として値をセットしようとする。
具体的には、Reactはレンダリングの過程で、挿入される値を文字列へと強制的に変換し、さらにHTMLタグとして解釈されそうな文字(`<`, `>`, `&`, `”`, `’` など)をエスケープしてくれる。
もし君が以下のようなコードを書いたとしても:
const userInput = ““;
// ReactはこれをそのままHTMLタグとして埋め込まず、文字列として出力する
// ブラウザのレンダリング結果は、タグが実行されずに「そのままの文字列」が表示されるだけだ
return
;
ブラウザはこれを `
—
「dangerouslySetInnerHTML」という名の警告
しかし、世の中にはCMSから配信されるリッチテキストや、マークダウンをパースしたHTMLをそのまま表示したいという泥臭い要件がある。そこで多くのエンジニアが手を出すのが `dangerouslySetInnerHTML` だ。
名前の通り、「危険を承知で」HTMLを挿入するプロパティだ。これを使うと、Reactの自動エスケープ機構はバイパスされる。Reactは「お前がHTMLを挿入したいというなら、もう責任は持たないぞ」と突き放すわけだ。
安全に使うための「現場の鉄則」
もしこれを使うなら、必ずサーバーサイドやフロントエンドのパイプラインでDOMPurifyを通すこと。これは絶対だ。
import DOMPurify from ‘dompurify’;
const SanitizedComponent = ({ dirtyHtml }) => {
// 信頼できないHTMLをサニタイズしてから注入する
const cleanHtml = DOMPurify.sanitize(dirtyHtml);
return (
);
};
ポイント:
1. DOMPurifyを噛ます: `dirtyHtml` をそのまま入れるのは自殺行為だ。
2. 依存関係を最小限に: 可能な限り、HTMLを注入せずにJSXで構造化できないか検討する。それが最大の防御だ。
3. 副作用を理解する: `dangerouslySetInnerHTML` で注入された要素は、Reactの差分検出(Virtual DOM)の管理外になることが多い。イベントリスナーの付与などが難しくなることを忘れてはいけない。
—
実務レベルで意識すべき「境界線」
中級者へのアドバイスとして、もう一つ重要な視点を伝えておこう。
Reactがエスケープするのはあくまで「JSXの `{ }` 内に埋め込まれる値」だ。もし君が `href` 属性にユーザー入力を直接突っ込んでいたらどうなる?
// 危険な例: javascript:スキームによるXSS
const userWebsite = “javascript:alert(‘XSS’)”;
// これもエスケープ対象にならない場合がある
return リンク;
Reactは属性値に対してもある程度の検証を行うが、`javascript:` スキームのようなプロトコル攻撃は、Reactの守備範囲外になることがある。「HTMLを注入する時」だけでなく、「属性を動的に生成する時」もまた戦場であるということを覚えておいてほしい。
まとめ:賢いエンジニアの矜持
Reactは強力な武器だが、それを扱うエンジニアの知識が浅ければ、簡単に足元をすくわれる。
- 基本はJSXのデータバインディングに任せる(エスケープされるから安全)。
- HTMLの注入が必要なら、必ずDOMPurify等の専門ツールで無害化する。
- 「dangerously」という名前を常に重く受け止める。
Reactのアーキテクチャを理解するということは、フレームワークが「何をやってくれていて、何をやっていないのか」という境界線を明確に引くことと同義だ。この境界線を意識できるようになった時、君の書くコードは一段階上の信頼性を獲得するはずだよ。
さあ、自信を持ってコードを書いていこう。何かあったらまたいつでも相談してくれ。

コメント