FlawOpen

flawopen.com/XSS/Markdown のレンダリング

Markdown のレンダリングは XSS に安全?

リファレンスガイド
要点

Markdown から生成した HTML は信頼できないコンテンツとして扱います。構文が許可するため、パーサーが生 HTML をそのまま保持する場合があります。Markdown の変換自体は出力をサニタイズしません。パーサーはマークアップの翻訳者であり、セキュリティ担当者ではありません。

信頼境界はどこか

CommonMark 仕様では、タグ形式の生 HTML はエスケープせずにレンダリングされます。実際の挙動はパーサー、オプション、プラグイン、ホストフレームワークによって異なります。たとえばMarkedは生成 HTML をサニタイズしないと明記しています。Markdown 構文だけでは入力の安全性を証明できません。サニタイザーは最終的な HTML の挿入先を保護する必要があります。

安全なレンダリング手順

危険 — 未処理の出力を挿入
const html = marked.parse(userMarkdown);
container.innerHTML = html; // パーサー出力は未サニタイズ
強化 — 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 は多層防御であり、サニタイズの代替ではありません。

本番前の確認項目

よくある質問

生 HTML を無効にすれば Markdown は安全ですか?

入力機能を一つ無効にできますが、それだけで安全とは言えません。リンク、画像、拡張機能、生成 HTML、挿入コンテキストを確認し、HTML 挿入前に出力をサニタイズしてください。

サニタイズ後に HTML を変更できますか?

避けてください。後からの変更で危険なマークアップが入り、サニタイザーの判断が無効になることがあります。変換を先に行い、最後にサニタイズします。

DOMPurify はあらゆる出力をどの文脈でも安全にしますか?

いいえ。文書化された脅威モデルに従って HTML 断片に使い、更新を保ち、狭いポリシーを設定します。JavaScript や CSS の文字列など別の文脈では再利用しないでください。

参考資料

関連項目 クロスサイトスクリプティング(XSS、CWE-79)の仕組みと各言語での防ぎ方 — flawopen.com SvelteはデフォルトでXSSを防げる? SVG アップロードは XSS のリスクになりますか? Vue v-htmlのXSSリスクと安全な使い方 WKWebView loadHTMLString は未信頼コンテンツに安全? 反射型・格納型・DOM ベース XSS の違いは? Android addJavascriptInterface のセキュリティリスク