【実務・中級編】 JSXにおけるエスケープ処理 – React実践ガイド

Reactの「自動エスケープ」は銀の弾丸ではない:XSSを防ぐための正しい作法

現場でコードレビューをしていると、ReactがXSS(クロスサイトスクリプティング)に対して「どれだけ寛容で、どれだけ厳しいか」を誤解しているエンジニアによく出会います。

「Reactを使っていれば、とりあえずXSSは大丈夫でしょ?」

もし君がそう思っているなら、少しだけ立ち止まって耳を貸してほしい。Reactの自動エスケープは非常に優秀だが、それはあくまで「Reactの流儀に従った場合」の話に過ぎないんだ。今日は、Reactが裏側で何をやっているのか、そしてなぜ`dangerouslySetInnerHTML`という名前がわざわざ「危険」を冠しているのか、その深淵を覗いてみよう。

—

Reactがデフォルトで行う「魔法」の正体

ReactでJSXを書くとき、変数を `{data}` のように埋め込むはずだ。このとき、Reactは内部的に `textContent` として値をセットしようとする。

具体的には、Reactはレンダリングの過程で、挿入される値を文字列へと強制的に変換し、さらにHTMLタグとして解釈されそうな文字(`<`, `>`, `&`, `”`, `’` など)をエスケープしてくれる。

もし君が以下のようなコードを書いたとしても:

const userInput = ““;

// ReactはこれをそのままHTMLタグとして埋め込まず、文字列として出力する
// ブラウザのレンダリング結果は、タグが実行されずに「そのままの文字列」が表示されるだけだ
return

{userInput}

;

ブラウザはこれを `

` の子要素として、単なる「テキスト」として扱う。DOMツリー上で `innerHTML` に直接代入されるわけではないから、ブラウザのパーサーはこれを実行可能なスクリプトとは認識しない。これがReactが提供する「デフォルトの守り」だ。

—

「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のアーキテクチャを理解するということは、フレームワークが「何をやってくれていて、何をやっていないのか」という境界線を明確に引くことと同義だ。この境界線を意識できるようになった時、君の書くコードは一段階上の信頼性を獲得するはずだよ。

さあ、自信を持ってコードを書いていこう。何かあったらまたいつでも相談してくれ。

コメント

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