🤮

React開発におけるサニタイズの必要性とXSS攻撃について

2025/02/07に公開

導入と概要

自身でTech blogを持ちたく、軽い気持ちでmicroCMSからHTML等のデータを受け取って表示するぐらいの簡単な開発をしていたのですが、その際に下記のようなコードを書きました。

<!-- contentは外部のAPIから取得したHTMLです -->
<div dangerouslySetInnerHTML={{__html: content}}></div>

偉大なChatGPT先生に「コードの評価して」的な質問をしたところ...
🤖< dangerouslySetInnerHTMLは注意して使ってください
みたいな感じで警告されたので、その流れでサニタイズとXSS攻撃について勉強することになりました。

多分、同じぐらいのレベル感の学習者さんもかなりいると思うので共有します。

dangerouslySetInnerHTMLはこんな感じの危険性があるよ! -> 対策はどうすればいいの???みたいな流れで書いているので適宜、読み替え、読み飛ばししていただければと思います。

参考

上記のを薄く伸ばして説明した感じのが本記事だと思ってください

XSS攻撃とは

XSS攻撃(クロスサイトスクリプティング)とは、攻撃者が悪意あるスクリプト(基本はjavascript)をウェズサイト常に埋め込んで不正な操作を行ったりする攻撃らしいです。

例えばAPI経由やユーザーが入力したHTMLを直にdangerouslySetInnnerHTMLで埋め込んだら、その中に悪意あるjavascript等が書かれていて不正な操作を防ぐことができないみたいな感じがイメージしやすいかと思います。

通常のReactではXSS等は既に対策されているらしいのですが、dangerouslySetInnnerHTMLでは外部から渡されたHTMLを直で表示するので危険性が高いらしいです。

最後の説明は少し怪しいので正しい説明が見たい方は下記の公式ドキュメントをお読みください
https://ja.react.dev/reference/react-dom/components/common#common-props

XSS攻撃の対策について(サニタイズ)

渡ってきたHTMLを直で書き込むのではなく、サニタイズ(消毒)を行うのが現状のベストプラクティスみたいです。

今回、私はDOMpurifyというライブラリを使わせて頂きました。
https://github.com/cure53/DOMPurify?tab=readme-ov-file

詳しくは上記のREADMEをみて欲しいのですが、私は下記の様な形で書きました。

import DOMPurify from "isomorphic-dompurify"
<!-- 他のコード -->
return(
<!-- 他のコード -->
<div dangerosulySetInnerHTML={{
    __html:DOMPurify.sanitize(content || "")
}} />
);

実は他にもdangerosulySetInnerHTMLにはパフォーマンス低下の問題点等あったのですが、今回の実装ではネックにはならなそうだったので特に触っていません。

パフォーマンス低下の問題点は気が向いたら触れます。

Discussion