安全でない可能性のあるHTMLコンテンツを、XSS(クロスサイトスクリプティング)攻撃などのセキュリティ上の脅威から保護するためにサニタイズ(無害化)してから表示する例を示す。
環境
vite@7.1.11
react@19.2.0
dompurify@3.3.0
リポジトリはこちら
コードの主要な機能と説明
App.jsx
import { useState } from 'react';
import { useSanitizedHtml } from './hooks/useSanitizedHtml'; // 作成したカスタムフックをインポート
import './App.css';
function App() {
// ユーザーや外部APIから取得された、サニタイズされていない可能性のあるHTML
const [userInput] = useState(`
<p>こちらは<strong>安全なコンテンツ</strong>です。</p>
<img src="x" onerror="alert('XSS Attack!')"> <a href="javascript:void(0)">クリックしても安全</a>
<script>console.log('Ignore this');</script> `);
// カスタムフックを使ってHTMLをサニタイズ
const safeHtml = useSanitizedHtml(userInput);
return (
<div className="content-container">
<h2>DOMPurifyでサニタイズしたHTMLの表示</h2>
{/* <div dangerouslySetInnerHTML={{__html: safeHtml}} /> */}
<div dangerouslySetInnerHTML={{__html: userInput}} />
<p>`onerror`属性や`script`タグは除去されています。</p>
</div>
);
}
export default App
userInput
サニタイズ前のHTMLコンテンツ(Dirty HTML)が格納されています。
onerror="alert('XSS Attack!')"
イベントハンドラを使ったXSSの例です。
<script>...</script>
スクリプトタグを使ったXSSの例です。
const safeHtml = useSanitizedHtml(userInput);
定義した userInput をインポートした useSanitizedHtml カスタムフックに渡し、サニタイズ処理を実行させる。処理後の安全なHTML文字列(Clean HTML)が safeHtml 変数に格納される。この変数の内容には、XSSにつながる要素や属性は含まれない。
useSanitizedHtml.js
import DOMPurify from 'dompurify';
/**
* 危険なHTML文字列を受け取り、DOMPurifyでサニタイズされた安全なHTMLを返す。
* @param {string} dirtyHtml サニタイズ前のHTML文字列
* @returns {string} サニタイズ後の安全なHTML文字列
*/
export const useSanitizedHtml = (dirtyHtml) => {
if (!dirtyHtml) return '';
const cleanHtml = DOMPurify.sanitize(dirtyHtml);// DOMPurifyでHTMLをサニタイズ。オプションで許可するタグや属性などを指定できる(例: {ALLOWED_TAGS: ['b', 'i', 'a']})
return cleanHtml;
};if (!dirtyHtml) return '';
入力が存在しない(null や空文字列など)場合は、そのまま空文字列を返す。
const cleanHtml = DOMPurify.sanitize(dirtyHtml);
受け取った dirtyHtml を DOMPurify.sanitize() メソッドに渡す。このメソッドは、<script> タグや onerror などの危険な属性を検知し、これらを完全に除去または無効化して無害なHTMLのみを残す。
return cleanHtml;
サニタイズされた安全なHTML文字列が呼び出し元(例: App.jsx)に返される。