DOMPurify は、HTML、MathML、SVG に対応した、DOM のみで動作する超高速・超高耐性の XSS サニタイザーです。
使い方も非常に簡単で、すぐに始められます。DOMPurify は 2014年2月に開発が開始され、現在はバージョン v3.4.15 に達しています。
DOMPurify は JavaScript として動作し、すべてのモダンブラウザ(Safari (10+)、Opera (15+)、Edge、Firefox、Chrome、および Blink・Gecko・WebKit を使用するほぼすべてのブラウザ)で動作します。MSIE やその他のレガシーブラウザでも壊れることはありません。単に何もしないだけです。
DOMPurify v2.5.9 は MSIE をサポートする最新バージョンです。MSIE と互換性のある重要なセキュリティアップデートについては、2.x ブランチ を使用してください。
自動テストは、プッシュのたびに現在のエンジン(Ubuntu、macOS、Windows 上の Chromium、Firefox、WebKit)で 9 種類のブラウザ/OS の組み合わせをカバーし、別のマトリックスでは古いエンジンのスナップショット(約 3 年前の Chromium 110、Firefox 108、WebKit 16.4 あたりまで)でスイートを再実行するため、古いブラウザでのリグレッションも検出されます。また、jsdom 上で DOMPurify を Node.js v20、v22、v24、v25、v26 でも実行しています。古い Node バージョンでも動作することは知られていますが、保証はありません。
DOMPurify は、Web 攻撃と XSS に関する豊富なバックグラウンドを持つセキュリティ専門家によって書かれています。ご安心ください。詳細については、セキュリティ目標と脅威モデル もお読みください。ぜひ、本当に読んでください。そして、詳細な内容を楽しみたい方は、攻撃クラスとバイパス履歴 のページに、DOMPurify が防御するパーサー変異、名前空間、クロバリング、テンプレートのトリックがカタログ化されています。
DOMPurify プロジェクトは、HTML Sanitizer API の作成に影響を与えました。この API はすでに多くのブラウザで提供されています。同じ機能は現在、WHATWG HTML 仕様 で直接標準化されています。
DOMPurify は HTML をサニタイズし、XSS 攻撃を防ぎます。たとえば、汚れた HTML でいっぱいの文字列を DOMPurify に渡すと、(設定を変更しない限り)クリーンな HTML を含む文字列が返されます。DOMPurify は危険な HTML を含むすべてを除去し、それによって XSS 攻撃やその他の厄介なものを防ぎます。また、非常に高速です。ブラウザが提供するテクノロジーを利用して、それを XSS フィルターに変換しています。ブラウザが速ければ速いほど、DOMPurify も速くなります。
簡単です。Web サイトに DOMPurify を含めるだけです。
### 圧縮・テスト済みの本番バージョンを使用する場合(ソースマップあり)```html
<script type="text/javascript" src="dist/purify.min.js"></script>
その後、以下のコードを実行して文字列をサニタイズできます。```js const clean = DOMPurify.sanitize(dirty);
Angularや類似のフレームワークでの作業が好きなら、こちらもどうぞ:```js
import DOMPurify from 'dompurify';
const clean = DOMPurify.sanitize('<b>hello there</b>');
生成されたHTMLは、innerHTMLを使ってDOM要素に書き込むことも、document.write()を使ってDOMに書き込むこともできます。それは完全にあなた次第です。
デフォルトでは、HTML、SVGおよびMathMLを許可していることに注意してください。HTMLのみが必要な場合(これは非常に一般的なユースケースかもしれません)、それも簡単に設定できます:```js
const clean = DOMPurify.sanitize(dirty, { USE_PROFILES: { html: true } });
### 足を撃ち抜くような落とし穴はありますか?
はい、注意してください。もし _最初に_ HTMLをサニタイズして、その _後に_ 変更を加えると、サニタイズの効果を**簡単に無効化してしまう**可能性があります。サニタイズ後のマークアップを別のライブラリに渡す場合は、そのライブラリが独自にHTMLをいじらないことを必ず確認してください。安全な使用方法や、よく考えてから使うべきタグ・属性については、[Security Goals & Threat Model](https://github.com/cure53/DOMPurify/wiki/Security-Goals-&-Threat-Model) を参照してください。また、後処理やマークアップのコンテキスト変更がなぜサニタイズを無効化するのかについては、[Attack Classes & Bypass History](https://github.com/cure53/DOMPurify/wiki/Attack-Classes-&-Bypass-History) を参照してください。
### わかりました、では次に進みましょう
マークアップをサニタイズした後、`DOMPurify.removed` プロパティを確認して、どの要素や属性が除去されたかを調べることもできます。ただし、このプロパティをセキュリティ上重要な判断に**使用しないでください**。これは好奇心旺盛な方のための小さなヘルパーにすぎません。
### サーバー上でDOMPurifyを実行する
DOMPurifyは技術的にはNode.jsのサーバーサイドでも動作します。私たちのサポートは[Node.jsのリリースサイクル](https://nodejs.org/en/about/previous-releases)に従うよう努めています。
サーバー上でDOMPurifyを実行するにはDOMが必要です。これはおそらく驚くことではないでしょう。通常は[jsdom](https://github.com/jsdom/jsdom)が選択肢の定番であり、_jsdom_ の最新バージョンを使用することを**強くお勧めします**。
なぜでしょうか? 古いバージョンの _jsdom_ は、DOMPurifyが100%正しく動作していてもXSSにつながるようなバグがあることが知られているためです。例えば _jsdom v19.0.0_ には**既知の攻撃ベクトル**があり、それは _jsdom v20.0.0_ で修正されています。そのため、_jsdom_ を最新に保つことを本当にお勧めします。
また、[happy-dom](https://github.com/capricorn86/happy-dom) のようなツールも存在しますが、現時点では**安全とは見なされていません**。DOMPurifyと _happy-dom_ を組み合わせることは現在推奨されておらず、XSSにつながる可能性が高いです。選択するサーバーサイドDOMがなぜ信頼できるコンピューティング基盤の一部となるのかについては、[Attack Classes & Bypass History](https://github.com/cure53/DOMPurify/wiki/Attack-Classes-&-Bypass-History) を参照してください。
それ以外については、サーバー上でDOMPurifyを使用しても問題ありません。おそらく。これは実際には _jsdom_ や、サーバーサイドで利用するDOMに依存します。それが許容できるのであれば、以下のようにして動作させることができます:```bash
npm install dompurify
npm install jsdom
jsdom(最新バージョンを使用してください)の場合、これでうまくいくはずです:```js const createDOMPurify = require('dompurify'); const { JSDOM } = require('jsdom');
const window = new JSDOM('').window; const DOMPurify = createDOMPurify(window); const clean = DOMPurify.sanitize('hello there');
あるいは、インポートを使った作業を好むなら、次のようにもできます:```js
import { JSDOM } from 'jsdom';
import DOMPurify from 'dompurify';
const window = new JSDOM('').window;
const purify = DOMPurify(window);
const clean = purify.sanitize('<b>hello there</b>');
お使いの特定の環境で動作させるのに問題がある場合は、多くの人が直面する問題を解決する素晴らしいプロジェクトである isomorphic-dompurify を検討してみてください。```bash npm install isomorphic-dompurify
I need the input content to translate. Please provide the chunk of Markdown content you'd like me to translate from English to Japanese.```js
import DOMPurify from 'isomorphic-dompurify';
const clean = DOMPurify.sanitize('<s>hello</s>');
もちろんデモがあります!DOMPurifyで遊ぶ
まず、修正に取り組めるよう、メールで直ちにご連絡ください。PGPキー
また、バグ報奨金の対象となる可能性もあります!Fastmailの素晴らしい方々がDOMPurifyを自社サービスで使用しており、当ライブラリをバグ報奨金の対象範囲に追加しています。そのため、DOMPurifyを回避または弱体化する方法を見つけた場合は、ぜひ彼らのウェブサイトとバグ報奨金情報もご覧ください。
浄化されたマークアップはどのように見えるのでしょうか?デモでは、多数の厄介な要素についてその様子を示しています。しかし、ここでもいくつかの小さな例を示しましょう!```js
DOMPurify.sanitize(''); // becomes
DOMPurify.sanitize('<g/onload=alert(2)//
'); // becomes DOMPurify.sanitize('
abcdef
'); // becomesabc
DOMPurify.sanitize('<mi//xlink:href="data:x,">'); // becomes DOMPurify.sanitize(''); // becomes| HELLO |
| HELLO |
これはほんの一部にすぎません。これらのサンプルが由来する攻撃クラスの完全な分類(mutation XSS、ネームスペース混乱、DOM clobbering、rawtextブレイクアウトなど)については、[Attack Classes & Bypass History](https://github.com/cure53/DOMPurify/wiki/Attack-Classes-&-Bypass-History) を参照してください。
## 何がサポートされていますか?
DOMPurifyは現在、HTML5、SVG、MathMLをサポートしています。DOMPurifyはデフォルトでCSSとHTMLカスタムデータ属性を許可します。DOMPurifyはShadow DOMもサポートしており、DOMテンプレートを再帰的にサニタイズします。また、DOMPurifyを使用すると、jQueryの `$()` および `elm.html()` APIで使用するためのHTMLを、既知の問題なくサニタイズすることもできます。デフォルトで許可される要素と属性の正確なセットについては、[Default TAGs & ATTRIBUTEs allow-list & blocklist](https://github.com/cure53/DOMPurify/wiki/Default-TAGs-ATTRIBUTEs-allow-list-&-blocklist) のWikiページを参照してください。
## Internet Explorerのようなレガシーブラウザではどうですか?
DOMPurifyは何も行いません。単に、入力した文字列をそのまま返すだけです。DOMPurifyは `isSupported` というプロパティを公開しており、これによってジョブを実行できるかどうかがわかるため、独自のバックアッププランを考案できます。
## DOMPurifyとTrusted Typesについてはどうですか?
バージョン1.0.9で、[Trusted Types API](https://github.com/w3c/webappsec-trusted-types)([MDN](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API))のサポートがDOMPurifyに追加されました。
バージョン2.0.0では、この点に関するDOMPurifyの動作を制御するための設定フラグが追加されました。
`DOMPurify.sanitize` がTrusted Types APIが利用可能な環境で使用され、`RETURN_TRUSTED_TYPE` が `true` に設定されている場合、文字列の代わりに `TrustedHTML` 値を返そうとします(`RETURN_DOM` および `RETURN_DOM_FRAGMENT` 設定オプションの動作は変わりません)。
DOMPurifyを使用して `trustedTypes` にポリシーを作成するには、`createHTML` が通常の文字列(`TrustedHTML` ではない)を期待するため、`RETURN_TRUSTED_TYPE: false` が必要であることに注意してください。以下の例にこれを示します。```js
window.trustedTypes.createPolicy('default', {
createHTML: (to_escape) =>
DOMPurify.sanitize(to_escape, { RETURN_TRUSTED_TYPE: false }),
});
TRUSTED_TYPES_POLICYが指定されていない場合、DOMPurifyはdompurifyという名前の独自の内部Trusted Typesポリシーを作成しようとします。ページが独自のポリシーを厳格なCSP(例:trusted-types my-organization)とともにすでに定義しており、dompurifyという名前のポリシーを許可していない場合、この試みはブラウザによってブロックされ、CSP違反とともにTrustedTypes policy dompurify could not be created.という警告がログに記録されます。
DOMPurifyが内部のフォールバックポリシーを作成しないようにするには、TRUSTED_TYPES_POLICY: nullを渡します。これは、独自のポリシーのcreateHTML内からDOMPurify.sanitizeを呼び出す場合に適切な選択であり、CSPのtrusted-types許可リストにdompurifyを追加する必要がないことを意味します。```js
window.trustedTypes.createPolicy('my-organization', {
createHTML: (input) =>
DOMPurify.sanitize(input, { TRUSTED_TYPES_POLICY: null }),
});
自身のラッピングポリシーを、その`createHTML`がすでに`DOMPurify.sanitize`を呼び出している場合に、DOMPurifyの`TRUSTED_TYPES_POLICY`として(たとえば`DOMPurify.setConfig({ TRUSTED_TYPES_POLICY: myPolicy })`経由で)渡し**ない**でください。これは定義上循環しています。サニタイズがポリシーを呼び出し、ポリシーは再びDOMPurifyを呼び出すことでサニタイズするためです。DOMPurifyは無限再帰を防ぐために、説明的な`TypeError`をスローします。自身のポリシーはDOMPurifyを呼び出すべきであり、DOMPurifyが自身のポリシーを呼び出すように設定すべきではありません。
この`default`ポリシーパターンをページ全体に自動的に適用したい場合(レガシーコード、サードパーティ製ウィジェット、簡単には見つけたり書き換えたりできない何千もの`innerHTML`代入を含む、すべてのHTMLシンクがサニタイズされるように)は、[DOMFortify](https://github.com/cure53/DOMFortify)を参照してください。これはDOMPurifyをバックエンドにした、まさにそのようなTrusted Typesの`default`ポリシーをインストールし、スクリプトシンク(`eval`、`script.src`など)を完全に拒否します。これは意図的に別個のプロジェクトです。DOMPurifyは焦点を絞ったサニタイザーであり続け、DOMFortifyが、意図的にDOMPurifyの範囲外にあるドキュメント全体の強制レイヤーを処理します。
## DOMPurifyを設定できますか?
はい。同梱されているデフォルト設定値はすでにかなり優れていますが、もちろん上書きできます。[`/demos`](https://github.com/cure53/DOMPurify/tree/main/demos)フォルダを確認して、[DOMPurifyをカスタマイズする](https://github.com/cure53/DOMPurify/tree/main/demos#what-is-this)方法の例を多数参照してください。
許可リストを広げる(`ADD_TAGS`、`ADD_ATTR`、`CUSTOM_ELEMENT_HANDLING`など)か、デフォルトを緩める前に、[よく考えてから許可すべきタグと属性](https://github.com/cure53/DOMPurify/wiki/Security-Goals-&-Threat-Model#dangerous-tags-and-attributes-think-twice-before-allow-listing)に目を通す価値があります。いくつかは、わかりにくい方法で危険です。
### 一般設定```js
// strip {{ ... }}, ${ ... } and <% ... %> to make output safe for template systems
// be careful please, this mode is not recommended for production usage.
// allowing template parsing in user-controlled HTML is not advised at all.
// only use this mode if there is really no alternative.
const clean = DOMPurify.sanitize(dirty, { SAFE_FOR_TEMPLATES: true });
// change how e.g. comments containing risky HTML characters are treated.
// be very careful, this setting should only be set to `false` if you really only handle
// HTML and nothing else, no SVG, MathML or the like.
// Otherwise, changing from `true` to `false` will lead to XSS in this or some other way.
const clean = DOMPurify.sanitize(dirty, { SAFE_FOR_XML: false });
// allow only elements, very strict const clean = DOMPurify.sanitize(dirty, { ALLOWED_TAGS: ['b'] });
// allow only and with style attributes
const clean = DOMPurify.sanitize(dirty, {
ALLOWED_TAGS: ['b', 'q'],
ALLOWED_ATTR: ['style'],
});
// allow all safe HTML elements but neither SVG nor MathML // note that the USE_PROFILES setting will override the ALLOWED_TAGS setting // so don't use them together const clean = DOMPurify.sanitize(dirty, { USE_PROFILES: { html: true } });
// allow all safe SVG elements and SVG Filters, no HTML or MathML const clean = DOMPurify.sanitize(dirty, { USE_PROFILES: { svg: true, svgFilters: true }, });
// allow all safe MathML elements and SVG, but no SVG Filters const clean = DOMPurify.sanitize(dirty, { USE_PROFILES: { mathMl: true, svg: true }, });
// change the default namespace from HTML to something different const clean = DOMPurify.sanitize(dirty, { NAMESPACE: 'http://www.w3.org/2000/svg', });
// leave all safe HTML as it is and add elements to block-list const clean = DOMPurify.sanitize(dirty, { FORBID_TAGS: ['style'] });
// leave all safe HTML as it is and add style attributes to block-list const clean = DOMPurify.sanitize(dirty, { FORBID_ATTR: ['style'] });
// extend the existing array of allowed tags and add to allow-list const clean = DOMPurify.sanitize(dirty, { ADD_TAGS: ['my-tag'] });
// extend the existing array of allowed attributes and add my-attr to allow-list const clean = DOMPurify.sanitize(dirty, { ADD_ATTR: ['my-attr'] });
// use functions to control which additional tags and attributes are allowed const allowlist = { one: ['attribute-one'], two: ['attribute-two'], }; const clean = DOMPurify.sanitize( '', { ADD_TAGS: (tagName) => { return Object.keys(allowlist).includes(tagName); }, ADD_ATTR: (attributeName, tagName) => { return allowlist[tagName]?.includes(attributeName) || false; }, } ); //
// prohibit ARIA attributes, leave other safe HTML as is (default is true) const clean = DOMPurify.sanitize(dirty, { ALLOW_ARIA_ATTR: false });
// prohibit HTML5 data attributes, leave other safe HTML as is (default is true) const clean = DOMPurify.sanitize(dirty, { ALLOW_DATA_ATTR: false });
### カスタムエレメントに関する制御動作```js
// DOMPurify allows to define rules for Custom Elements. When using the CUSTOM_ELEMENT_HANDLING
// literal, it is possible to define exactly what elements you wish to allow (by default, none are allowed).
//
// The same goes for their attributes. By default, the built-in or configured allow.list is used.
//
// You can use a RegExp literal to specify what is allowed or a predicate, examples for both can be seen below.
// When using a predicate function for attributeNameCheck, it can optionally receive the tagName as a second parameter
// for more granular control over which attributes are allowed for specific elements.
// The default values are very restrictive to prevent accidental XSS bypasses. Handle with great care!
const clean = DOMPurify.sanitize(
'<foo-bar baz="foobar" forbidden="true"></foo-bar><div is="foo-baz"></div>',
{
CUSTOM_ELEMENT_HANDLING: {
tagNameCheck: null, // no custom elements are allowed
attributeNameCheck: null, // default / standard attribute allow-list is used
allowCustomizedBuiltInElements: false, // no customized built-ins allowed
},
}
); // <div is=""></div>
const clean = DOMPurify.sanitize(
'<foo-bar baz="foobar" forbidden="true"></foo-bar><div is="foo-baz"></div>',
{
CUSTOM_ELEMENT_HANDLING: {
tagNameCheck: /^foo-/, // allow all tags starting with "foo-"
attributeNameCheck: /baz/, // allow all attributes containing "baz"
allowCustomizedBuiltInElements: true, // customized built-ins are allowed
},
}
); // <foo-bar baz="foobar"></foo-bar><div is="foo-baz"></div>
const clean = DOMPurify.sanitize(
'<foo-bar baz="foobar" forbidden="true"></foo-bar><div is="foo-baz"></div>',
{
CUSTOM_ELEMENT_HANDLING: {
tagNameCheck: (tagName) => tagName.match(/^foo-/), // allow all tags starting with "foo-"
attributeNameCheck: (attr) => attr.match(/baz/), // allow all containing "baz"
allowCustomizedBuiltInElements: true, // allow customized built-ins
},
}
); // <foo-bar baz="foobar"></foo-bar><div is="foo-baz"></div>
// Example with attributeNameCheck receiving tagName as a second parameter
const clean = DOMPurify.sanitize(
'<element-one attribute-one="1" attribute-two="2"></element-one><element-two attribute-one="1" attribute-two="2"></element-two>',
{
CUSTOM_ELEMENT_HANDLING: {
tagNameCheck: (tagName) => tagName.match(/^element-(one|two)$/),
attributeNameCheck: (attr, tagName) => {
if (tagName === 'element-one') {
return ['attribute-one'].includes(attr);
} else if (tagName === 'element-two') {
return ['attribute-two'].includes(attr);
} else {
return false;
}
},
allowCustomizedBuiltInElements: false,
},
}
); // <element-one attribute-one="1"></element-one><element-two attribute-two="2"></element-two>
// extend the existing array of elements that can use Data URIs const clean = DOMPurify.sanitize(dirty, { ADD_DATA_URI_TAGS: ['a', 'area'] });
// extend the existing array of elements that are safe for URI-like values (be careful, XSS risk) const clean = DOMPurify.sanitize(dirty, { ADD_URI_SAFE_ATTR: ['my-attr'] });
### 許可された属性値の制御```js
// allow external protocol handlers in URL attributes (default is false, be careful, XSS risk)
// by default only http, https, ftp, ftps, tel, mailto, callto, sms, cid, xmpp and matrix are allowed.
const clean = DOMPurify.sanitize(dirty, { ALLOW_UNKNOWN_PROTOCOLS: true });
// allow specific protocol handlers in URL attributes via regex (default is false, be careful, XSS risk)
// by default only (protocol-)relative URLs, http, https, ftp, ftps, tel, mailto, callto, sms, cid, xmpp and matrix are allowed.
// Default RegExp: /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i;
const clean = DOMPurify.sanitize(dirty, {
ALLOWED_URI_REGEXP:
/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i,
});
// return a DOM HTMLBodyElement instead of an HTML string (default is false) const clean = DOMPurify.sanitize(dirty, { RETURN_DOM: true });
// return a DOM DocumentFragment instead of an HTML string (default is false) const clean = DOMPurify.sanitize(dirty, { RETURN_DOM_FRAGMENT: true });
// use the RETURN_TRUSTED_TYPE flag to turn on Trusted Types support if available const clean = DOMPurify.sanitize(dirty, { RETURN_TRUSTED_TYPE: true }); // will return a TrustedHTML object instead of a string if possible
// use a provided Trusted Types policy const clean = DOMPurify.sanitize(dirty, { // supplied policy must define createHTML and createScriptURL TRUSTED_TYPES_POLICY: trustedTypes.createPolicy('dompurify', { createHTML(s) { return s; }, createScriptURL(s) { return s; }, }), });
// opt out of DOMPurify's internal dompurify Trusted Types policy entirely
// (useful when your CSP trusted-types allowlist does not include dompurify)
const clean = DOMPurify.sanitize(dirty, { TRUSTED_TYPES_POLICY: null });
### サニタイズ方法への影響```js
// return entire document including <html> tags (default is false)
const clean = DOMPurify.sanitize(dirty, { WHOLE_DOCUMENT: true });
// disable DOM Clobbering protection on output (default is true, handle with care, minor XSS risks here)
const clean = DOMPurify.sanitize(dirty, { SANITIZE_DOM: false });
// enforce strict DOM Clobbering protection via namespace isolation (default is false)
// when enabled, isolates the namespace of named properties (i.e., `id` and `name` attributes)
// from JS variables by prefixing them with the string `user-content-`
const clean = DOMPurify.sanitize(dirty, { SANITIZE_NAMED_PROPS: true });
// keep an element's content when the element is removed (default is true)
const clean = DOMPurify.sanitize(dirty, { KEEP_CONTENT: false });
// glue elements like style, script or others to document.body and prevent unintuitive browser behavior in several edge-cases (default is false)
const clean = DOMPurify.sanitize(dirty, { FORCE_BODY: true });
// remove all <a> elements under <p> elements that are removed
const clean = DOMPurify.sanitize(dirty, {
FORBID_CONTENTS: ['a'],
FORBID_TAGS: ['p'],
});
// extend the default FORBID_CONTENTS list to also remove <a> elements under <p> elements
const clean = DOMPurify.sanitize(dirty, {
ADD_FORBID_CONTENTS: ['a'],
FORBID_TAGS: ['p'],
});
// change the parser type so sanitized data is treated as XML and not as HTML, which is the default
const clean = DOMPurify.sanitize(dirty, {
PARSER_MEDIA_TYPE: 'application/xhtml+xml',
});
// use the IN_PLACE mode to sanitize a node "in place", which is much faster depending on how you use DOMPurify const dirty = document.createElement('a'); dirty.setAttribute('href', 'javascript:alert(1)');
const clean = DOMPurify.sanitize(dirty, { IN_PLACE: true }); // see https://github.com/cure53/DOMPurify/issues/288 for more info
以下に、チャンク43/45の翻訳を示します。
[さらに多くの例はこちら](https://github.com/cure53/DOMPurify/tree/main/demos#what-is-this)にあり、DOMPurifyを実行、カスタマイズ、設定する方法を確認できます。
## 永続的な設定
毎回同じ設定を`DOMPurify.sanitize`に渡す代わりに、`DOMPurify.setConfig`メソッドを使用できます。設定は、次に`DOMPurify.setConfig`を呼び出すまで、または`DOMPurify.clearConfig`を呼び出してリセットするまで保持されます。アクティブな設定は1つだけであることに注意してください。つまり、設定が設定されると、`DOMPurify.sanitize`に渡される追加の設定パラメータはすべて無視されます。
## フック
DOMPurifyでは、`DOMPurify.addHook`メソッドを使用して1つ以上の関数を次のフックのいずれかにアタッチすることで、機能を拡張できます。
- `beforeSanitizeElements`
- `uponSanitizeElement`('s'なし - すべての要素に対して呼び出されます)
- `afterSanitizeElements`
- `beforeSanitizeAttributes`
- `uponSanitizeAttribute`
- `afterSanitizeAttributes`
- `beforeSanitizeShadowDOM`
- `uponSanitizeShadowNode`
- `afterSanitizeShadowDOM`
コールバックには、現在処理中のDOMノード、必要に応じて検証済みのノードと属性データを含むリテラル、およびDOMPurify設定が渡されます。APIの使用方法の良い例については、[MentalJSフックデモ](https://github.com/cure53/DOMPurify/blob/main/demos/hooks-mentaljs-demo.html)を確認してください。
_例_:```js
DOMPurify.addHook(
'uponSanitizeAttribute',
function (currentNode, hookEvent, config) {
// Do something with the current node
// You can also mutate hookEvent for current node (i.e. set hookEvent.forceKeepAttr = true)
// For other than 'uponSanitizeAttribute' hook types hookEvent equals to null
}
);
sanitize()を呼び出す際の注意点DOMPurify.sanitize()は再入可能ではありません。 フックの内部や、CUSTOM_ELEMENT_HANDLING.tagNameCheckやattributeNameCheckなどの設定コールバックから呼び出さないでください。これらのコールバックは、アクティブなサニタイズ処理の_途中_で実行されます。
ネストされたsanitize()呼び出しは、渡された設定を読み直し、その過程で外側の処理がまだ使用している設定を置き換えます。外側のドキュメントの残りは、その後、あなたの設定ではなくネストされた呼び出しの設定に対してサニタイズされます。ネストされた呼び出しは通常デフォルト設定で実行されるため、厳格なALLOWED_TAGS許可リストが、エラーも警告もなしに、ドキュメントの途中で暗黙的にデフォルトのものに戻ってしまう可能性があります。
属性値内に含まれるHTMLフラグメントなど、ネストされたマークアップをサニタイズする必要がある場合は、2つの安全な選択肢があります。呼び出しごとに設定を渡す代わりに、DOMPurify.setConfigを使用して設定を一度だけ設定する方法です(永続的な設定はネストされた呼び出しと共有され、処理全体を通して有効なままです)。または、フック中にフラグメントを収集し、外側の呼び出しが戻った_後_に、別のsanitize()呼び出しでサニタイズする方法です。
| オプション | 追加バージョン | 備考 |
|---|---|---|
| SAFE_FOR_JQUERY | 2.1.0 | 置き換えは不要です。 |
現在、GitHub ActionsとPlaywrightを組み合わせて使用しています。これにより、すべてのコミットで関連する最新のブラウザで問題なく動作することを確認でき、さらにスケジュールされた別のワークフローとマージ時のワークフローが、古いエンジンのスナップショットでテストスイートを再実行するため、古いブラウザでの破損も検出されます。ビルドログはこちらで確認できます: https://github.com/cure53/DOMPurify/actions
さらに、npm run testを実行することでローカルでテストを実行できます。
関連するすべてのコミットは、追加のセキュリティのために鍵0x24BB6BF4で署名されます(2016年4月8日以降)。
npm i)npmを公式にサポートしています。GitHub Actionsワークフローは、npmを使用して依存関係をインストールするように設定されています。非推奨のバージョンのnpmを使用する場合、インストールされる依存関係のバージョンを完全に保証することはできず、予期しない問題が発生する可能性があります。
コードの一貫性を確保するために、pre-commitワークフローの一部としてxoを介したESLintを使用しています。さらに、ソースとMarkdownのフォーマットにはPrettierを使用し、/distアセットはrollupを通じてビルドされます。
以下がnpmスクリプトです:
npm run dev - ソースの変更を監視しながら、圧縮されていないUMDバンドルをビルドしますnpm run test - ソースをリントし、jsdomを通じてテストを実行し、Playwrightを介してChromiumでブラウザテストを実行します
npm run test:jsdom - jsdomを通じてのみテストを実行しますnpm run test:happydom - happy-domを通じてテストスイートを実行します(サポートされていない環境。堅牢性チェックとして維持されており、互換性の約束ではありません)npm run test:browser - Playwrightを通じてのみテストを実行しますnpm run test:browser:legacy - 古いブラウザエンジンでテストスイートを実行します(PW_MODULEを固定された古いPlaywrightインストールに向けます。.github/workflows/legacy-browsers.ymlを参照)npm run test:ci - jsdomとPlaywrightのCIテストフローを実行しますnpm run test:fuzz - sanitize()とCONFIGをカバーする小さなファザーを実行しますnpm run bench - ビルドされたdist/purify.cjsに対してjsdomマイクロベンチマークを実行します(最初にビルドします。--jsonと--compare a.json b.jsonはブランチ間のA/B実行をサポートします。結果は方向性を示すものであり、ユーザー向けの主張は実際のブラウザで確認してください)npm run coverage - インストルメント化されたバンドルをビルドし、jsdomスイートを実行し、ローカルのHTML行/分岐カバレッジレポートをcoverage/index.htmlに書き込みます(jsdomスコープのみ。CIでは実行されません)
npm run build:cov - インストルメント化されたカバレッジバンドルのみをビルドしますnpm run lint - xoを介したESLintを使用してソースをリントしますnpm run format - PrettierでJavaScript/TypeScriptおよびMarkdownソースをフォーマットします
npm run format:js - JavaScript/TypeScriptソースのみをフォーマットしますnpm run format:md - Markdownファイルのみをフォーマットしますnpm run build - 型宣言と配布バンドルをビルドし、生成された型を修正およびクリーンアップします
npm run build:types - TypeScript宣言ファイルのみを出力しますnpm run build:rollup - すべてのRollupバンドルをビルドしますnpm run build:umd - 圧縮されていないUMDバンドルのみをビルドしますnpm run build:umd:min - 圧縮されたUMDバンドルのみをビルドしますnpm run build:es - ESモジュールバンドルのみをビルドしますnpm run build:cjs - CommonJSバンドルのみをビルドしますnpm run build:fix-types - 生成された型ファイルを後処理しますnpm run build:cleanup - 一時的な生成型出力をクリーンアップしますnpm run verify-typescript - TypeScript検証スクリプトを実行しますnpm run commit-amend-build - ビルド出力を修正するためのメンテナー用ヘルパースクリプトを実行します注: すべての実行スクリプトはnpm run <script>でトリガーされます。
他にもnpmスクリプトはありますが、主にCIとの統合のため、または各コミットで配布ビルドファイルを修正するなどの「プライベート」な目的のためのものです。
DOMPurifyのセキュリティ上重要なリリースが公開されるたびに通知するメーリングリストを維持しています。つまり、誰かがバイパスを発見し、リリースで修正した場合(バイパスが発見されたときは常に発生します)、そのリストにメールが送信されます。これは通常、バイパスを知ってから数分から数時間以内に発生します。リストへの登録はこちらから:
機能リリースはこのリストでは通知されません。
多くの人々がDOMPurifyを今日の姿にするのを助けてきました。彼らに感謝の意を表します!
gnyselcuk、leechristensen、offset、Bankde、lukewarlow、DEMON1A、fg0x0、kodareef5、DavidOliver、1Jesper1、bencalif、trace37labs、eddieran、christos-eth、researchatfluidattacks、frevadiscor、Rotzbua、binhpv、MariusRumpf、prasadrajandran、Cybozu 💛💸、hata6502 💸、openclaw 💸、intra-mart-dh 💸、nelstrom ❤️、hash_kitten ❤️、kevin_mizu ❤️、icesfont ❤️、reduckted ❤️、dcramer 💸、JGraph 💸、baekilda 💸、Healthchecks 💸、Sentry 💸、jarrodldavis 💸、CynegeticIO、ssi02014 ❤️、GrantGryczan、Lowdefy、granlem、oreoshake、tdeekens ❤️、peernohell ❤️、is2ei、SoheilKhodayari、franktopel、NateScarlet、neilj、fhemberger、Joris-van-der-Wel、ydaniv、terjanq、filedescriptor、ConradIrwin、gibson042、choumx、0xSobky、styfle、koto、tlau88、strugee、oparoz、mathiasbynens、edg2s、dnkolegov、dhardtke、wirehead、thorn0、styu、mozfreddyb ❤️、mikesamuel、jorangreef、jimmyhchan、jameydeorio、jameskraus、hyderali、hansottowirtz、hackvertor、freddyb、flavorjones、djfarrelly、devd、camerondunford、buu700、buildog、alabiaga、Vector919、Robbert、GreLI、FuzzySockets、ArtemBernatskyy、@garethheyes、@shafigullin、@mmrupp、@irsdl、ShikariSenpai、ansjdnakjdnajkd、@asutherland、@mathias、@cgvwzq、@robbertatwork、@giutro、@CmdEngineer_、@avr4mit、davecardwell、Develop-KIM、asamuzaK、fishjojo1 ❤️、Rikuxx0、donmccurdy、hhk-png、elrion018、michalnieruchalski-tiugo、reey、KanhaKanhaiya、odaysec、Akokonunes、alirezarouhbakhsh、Jaybhade、そして特に@securitymb ❤️と@masatokinugawa ❤️に感謝します。