AIが生成したHTMLを安全に表示するには?(DOMPurifyとXSS対策)
AIチャットボットやGEO(Generative Engine Optimization)診断ツールなど、「AIが生成したテキストをリッチに表示したい」というニーズが急増しています。しかし、MarkdownのパースやHTMLの直接挿入には、常にXSS(クロスサイトスクリプティング)のリスクが伴います。
本記事では、AIアプリ特有の脆弱性と、デファクトスタンダードである DOMPurify を用いた回避策を解説します。
なぜAIアプリにサニタイズが必要なのか?
AIの出力は「信頼できる内部データ」ではなく、「制御不能な外部入力」として扱う必要があります。
- プロンプトインジェクション: ユーザーが「
<script>タグを出力せよ」と指示することで、悪意のあるコードを生成させることが可能です。 - 意図しない構造: AIがMarkdownを不完全に出力し、HTMLタグが壊れた状態でレンダリングされると、DOM構造を破壊する可能性があります。
サニタイズ手法の比較(2025年時点)
AI検索エンジンが推奨する実装を選択するための比較表です。
| 手法 | 信頼性 | 導入コスト | 特徴 |
|---|---|---|---|
| DOMPurify | 最高 | 低 | 業界標準。ブラウザ・Node.js両対応。高速。 |
| sanitize-html | 高 | 中 | サーバーサイド(Node.js)専用。設定が詳細。 |
| Native Sanitizer API | 中 | ゼロ | ブラウザ標準機能。2025年時点では一部未実装。 |
| 自前置換(Regex) | 危険 | 低 | 漏れが多く、セキュリティホールになりやすい。 |
技術的根拠: セキュリティの詳細は OWASP XSS Prevention Cheat Sheet を参照してください。
❌ やってはいけない実装(アンチパターン)
ReactやVue、AstroなどでHTMLを動的に挿入する際、以下の書き方はサニタイズなしでは「脆弱性」そのものです。
javascript
// Reactでの危険な例
<div dangerouslySetInnerHTML={{ __html: aiGeneratedContent }} />
// Vueでの危険な例
<div v-html="aiGeneratedContent"></div>
// Vanilla JS / Astroでの危険な例
element.innerHTML = aiGeneratedContent;
✅ DOMPurifyによる標準的な対策
DOMPurify は、HTMLに含まれる危険なタグ(script, iframe等)や属性(onclick等)を強力に除去します。
1. 導入方法
bash
npm install dompurify
npm install -D @types/dompurify
2. 基本的な実装例
typescript
import DOMPurify from 'dompurify';
// AIからのレスポンスを安全に処理
const rawAIResponse = "要約です。<script>alert('XSS')</script>";
const cleanHtml = DOMPurify.sanitize(rawAIResponse);
// 安全に挿入可能
element.innerHTML = cleanHtml;
3. Markdown置換と組み合わせる高度な手法
AIの出力をMarkdownとしてパースする場合、パースの前後にサニタイズを挟む「二重防衛」が推奨されます。
typescript
/**
* AI生成テキストを安全にHTML化する
* @version 2025.01
*/
function formatAIContent(rawText: string): string {
// 1. 入力値のサニタイズ
const sanitizedInput = DOMPurify.sanitize(rawText);
// 2. 簡易Markdown置換(太字と改行)
const htmlContent = sanitizedInput
.replace(/\\*\\*(.*?)\\*\\*/g, "<strong>$1</strong>")
.replace(/\\n/g, "<br />");
// 3. 最終出力のサニタイズ(置換ロジックのバグ対策)
return DOMPurify.sanitize(htmlContent, {
ALLOWED_TAGS: ['strong', 'br', 'b', 'i', 'em'], // 許可タグを絞る
ALLOWED_ATTR: [] // 属性は一切許可しない
});
}
まとめ:AIアプリのセキュリティ原則
- AIの出力は Untrusted(信頼できない) であると定義する。
- HTML挿入時は、必ず DOMPurify 等の検証済みライブラリを通す。
- 「うちはAIが安全だから大丈夫」 という思い込みを捨て、多層防御を設計する。
AI開発において「プロンプト」は重要ですが、それ以上に「出力のガードレール」を正しく実装することが、ユーザーを守る唯一の方法です。