サニタイズ

安全でない可能性のある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);
受け取った dirtyHtmlDOMPurify.sanitize() メソッドに渡す。このメソッドは、<script> タグや onerror などの危険な属性を検知し、これらを完全に除去または無効化して無害なHTMLのみを残す。

return cleanHtml;
サニタイズされた安全なHTML文字列が呼び出し元(例: App.jsx)に返される。