flawopen.com/XSS/Markdown のレンダリング
Markdown のレンダリングは XSS に安全?
Markdown から生成した HTML は信頼できないコンテンツとして扱います。構文が許可するため、パーサーが生 HTML をそのまま保持する場合があります。Markdown の変換自体は出力をサニタイズしません。パーサーはマークアップの翻訳者であり、セキュリティ担当者ではありません。
信頼境界はどこか
CommonMark 仕様では、タグ形式の生 HTML はエスケープせずにレンダリングされます。実際の挙動はパーサー、オプション、プラグイン、ホストフレームワークによって異なります。たとえばMarkedは生成 HTML をサニタイズしないと明記しています。Markdown 構文だけでは入力の安全性を証明できません。サニタイザーは最終的な HTML の挿入先を保護する必要があります。
安全なレンダリング手順
const html = marked.parse(userMarkdown); container.innerHTML = html; // パーサー出力は未サニタイズ
import DOMPurify from "dompurify";
const html = marked.parse(userMarkdown);
container.innerHTML = DOMPurify.sanitize(html, {
USE_PROFILES: { html: true }
});
この例は DOMPurify の HTML 専用プロファイルを使います。この画面では SVG や MathML が不要なためです。製品に必要な機能だけを許可してください。サニタイズ済みのマークアップを変更したり、挿入前に別の HTML 変換ライブラリへ渡したりすると保証が無効になることがあります。リッチ HTML が不要なら、フレームワークの安全なテキスト表示を優先します。Content Security Policy と Trusted Types は多層防御であり、サニタイズの代替ではありません。
本番前の確認項目
- ✓Markdown パーサーのバージョンを固定し、生 HTML、プラグイン、URL の設定を確認する。
- ✓最終 HTML を、保守されている許可リスト型サニタイザーで挿入直前に処理する。
- ✓要素、属性、URL スキームを必要な機能に限定する。
- ✓サニタイズ後に編集・再解析しない。変換が必要なら変換後に再度サニタイズする。
- ✓実際のパーサー設定と挿入先をテストし、サニタイザーを更新する。
よくある質問
入力機能を一つ無効にできますが、それだけで安全とは言えません。リンク、画像、拡張機能、生成 HTML、挿入コンテキストを確認し、HTML 挿入前に出力をサニタイズしてください。
避けてください。後からの変更で危険なマークアップが入り、サニタイザーの判断が無効になることがあります。変換を先に行い、最後にサニタイズします。
いいえ。文書化された脅威モデルに従って HTML 断片に使い、更新を保ち、狭いポリシーを設定します。JavaScript や CSS の文字列など別の文脈では再利用しないでください。