0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【セキュリティ】XSS 防御における“実質標準”の最強サニタイザ— DOMPurify

0
Posted at

はじめに

DOMPurify は、Web アプリケーションにおける HTML サニタイズの事実上の標準ライブラリだ。
世界中の大規模サービス(Google, GitHub, Moodle, Discourse, Nextcloud など)が採用しており、その理由は 「速い・安全・堅牢・最新攻撃に追従」 の 4 点に尽きる。

この記事では、DOMPurify の仕組みから実践的な使い方、XSS 全種類への効果、CSP や Trusted Types との併用などをわかりやすく説明する。


1. DOMPurify とは?

DOMPurify は ユーザー入力を HTML として扱う際に、その中から悪意あるコードだけを除去する ライブラリ。

つまり:

  • <b>太字</b> のような 許可したい装飾 HTML はそのまま残し
  • <script>...</script><img onerror=...> などの XSS 要素は自動で除去する

という、非常に精巧なフィルタリングを行ってくれる。

特徴:

  • 超高速
  • 超安全
  • 更新頻度が高く脆弱性研究に強い
  • ほぼ全ブラウザ対応
  • サーバー側(Node.js)でも動作
  • SVG・MathML なども安全化可能

“サニタイズ=DOMPurify” と言われるほど信頼性が高い。


2. DOMPurify が防げる攻撃

DOMPurify はあらゆる HTML ベースの XSS を防ぐ。

XSS 種類 DOMPurify 備考
Stored XSS 完全除去
Reflected XSS 完全除去
DOM-Based XSS(innerHTML) innerHTML 前に sanitize すれば安全
SVG XSS SVG の危険タグ削除
MathML XSS MathML の unsafe 部分を除去
URL ベース XSS URL sanitization が必要な場合あり
Script gadgets 既知の bypass に強い

現代的 XSS の多くが HTML を経由するため、DOMPurify を使えば攻撃面は劇的に狭まる。


3. 基本的な使い方(最短 2 行)

const clean = DOMPurify.sanitize(userInput);
element.innerHTML = clean;

これだけで、
<script>onerror、危険属性がすべて除去された安全な HTMLが得られる。


4. 許可したい HTML を制御するオプション

DOMPurify は「ホワイトリスト方式」で動いている。
つまり、許可されていないタグ・属性はすべて除去される。

許可するタグの指定

DOMPurify.sanitize(userInput, {
  ALLOWED_TAGS: ['b', 'i', 'a', 'p']
});

許可する属性の指定

DOMPurify.sanitize(userInput, {
  ALLOWED_ATTR: ['href', 'target']
});

URL スキームを制限する(必須級)

XSS bypass の定番が href="javascript:alert(1)"
DOMPurify はこれを自動ブロックするが、さらに堅牢にするなら:

DOMPurify.sanitize(userInput, {
  ALLOWED_URI_REGEXP: /^https?:\/\//i
});

HTTPS/HTTP 以外は拒否する設定。


5. “Super Safe Mode”(高度な XSS 防御)

完全に安全な HTML のみ許可する設定:

DOMPurify.sanitize(userInput, {
  USE_PROFILES: { html: true }
});

または:

DOMPurify.sanitize(userInput, {
  ALLOWED_TAGS: [],
  ALLOWED_ATTR: []
});

→ 最強の「完全プレーンテキストモード」。


6. Node.js / SSR でも使える

サーバー側レンダリング時の XSS を防ぐことも可能。

const createDOMPurify = require('dompurify');
const { JSDOM } = require('jsdom');

const window = new JSDOM('').window;
const DOMPurify = createDOMPurify(window);

const clean = DOMPurify.sanitize(dirtyHTML);

Next.js、Nuxt など SSR ベースのフレームワークでも使用可能。


7. DOMPurify × Trusted Types(XSS 完全封殺コンボ)

DOMPurify は強いが、innerHTML の危険性そのものが消えるわけではない。
そこで併用すべきなのが Trusted Types

Trusted Types の CSP 設定

Content-Security-Policy:
  require-trusted-types-for 'script';
  trusted-types dompurify;

DOMPurify を Trusted Types 化

const policy = trustedTypes.createPolicy('dompurify', {
  createHTML: (input) => DOMPurify.sanitize(input)
});

element.innerHTML = policy.createHTML(userInput);

これにより:

  • DOMPurify 以外から innerHTML に HTML を流し込めない
  • “開発者のミス” 自体が技術的にブロックされる
  • DOM XSS が ほぼ完全に封じられる

Google の推奨構成でもある。


8. DOMPurify の弱点と注意点

弱点というより、認識すべき仕様。

注意点 説明
JS 文脈のエスケープはできない <script> は除去できるが JS の中に文字列として埋め込む場合は別対策が必要
URL sanitization は別処理が必要 javascript: などは除去されるが設計上の考慮が必要
完全にフレームワーク任せは危険 React/Vue の dangerous API には要注意
HTML5 の仕様変更に追従するため更新が必要 最新版を使うのが必須

“DOMPurify だけで XSS 全部を倒せる”は誤解。
あくまで HTML サニタイズ担当。


9. 現代の最強構成:DOMPurify + CSP + Trusted Types

XSS を本気で防ぎたいなら、この 3 点セットが最強。

レイヤー 防ぐもの
出力エスケープ 基本の XSS 70%
DOMPurify HTML ベースの XSS を ほぼ無力化
CSP(script-src 'self') 攻撃者の JS 実行自体を阻止
Trusted Types innerHTML の危険性をゼロにする

この構成を採用すると、
実質的に XSS の攻撃面が枯渇する。


まとめ:DOMPurify は“使わない理由がない”最強ライブラリ

DOMPurify は:

  • 速い
  • 安全
  • 堅牢
  • 更新が早い
  • 大規模サービスでも運用実績豊富

という、サニタイズ界のオールラウンダー。

もちろん DOMPurify だけで万能ではないが、
“HTML をユーザーに見せる Web アプリで必須級” の存在であることは間違いない。

ユーザーが入力する“HTML”がある限り、DOMPurify の出番は終わらない。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?