العودة إلى التحديثات
New releaseSep 7, 2026

DOMPurify v3.4.15

DOMPurify - أداة تعقيم XSS تعمل على DOM فقط، فائقة السرعة ومتسامحة للغاية، لـ HTML وMathML وSVG. يعمل DOMPurify بإعداد افتراضي آمن، لكنه يوفر الكثير من خيارات الإعداد والخطافات. عرض توضيحي:

مشاركة

DOMPurify

npm License Downloads dependents npm package minimized gzipped size (select exports) Cloudback

OpenSSF Best Practices Build & Test OpenSSF Scorecard Socket Badge snyk.io package health

DOMPurify هو مُنقّي XSS سريع للغاية ومتسامح للغاية ويعمل على DOM فقط، مخصص لـ HTML وMathML وSVG.

كما أنه سهل الاستخدام والبدء معه بشكل كبير. بدأ مشروع DOMPurify في فبراير 2014 وقد وصل في هذه الأثناء إلى الإصدار v3.4.15.

يعمل DOMPurify كـ JavaScript ويعمل في جميع المتصفحات الحديثة (Safari (10+), Opera (15+), Edge, Firefox وChrome - بالإضافة إلى أي شيء آخر تقريبًا يستخدم Blink أو Gecko أو WebKit). لا يتعطل على MSIE أو المتصفحات القديمة الأخرى. بل لا يقوم بأي شيء ببساطة.

لاحظ أن DOMPurify v2.5.9 هو أحدث إصدار يدعم MSIE. للحصول على تحديثات أمنية مهمة متوافقة مع MSIE، يرجى استخدام فرع 2.x.

تغطي اختباراتنا الآلية 9 مجموعات من المتصفحات/أنظمة التشغيل على المحركات الحالية (Chromium وFirefox وWebKit عبر Ubuntu وmacOS وWindows) في كل عملية دفع، كما تعيد مصفوفة منفصلة تشغيل مجموعة الاختبارات على لقطات محركات أقدم (حتى حوالي Chromium 110 وFirefox 108 وWebKit 16.4، أي حوالي ثلاث سنوات) بحيث يتم اكتشاف الانحدارات على المتصفحات القديمة أيضًا. كما نقوم بتشغيل Node.js v20 وv22 وv24 وv25 وv26 مع DOMPurify على jsdom. من المعروف أن إصدارات Node الأقدم تعمل أيضًا، لكن... لا توجد ضمانات.

DOMPurify مكتوب بواسطة خبراء أمنيين لديهم خلفية واسعة في هجمات الويب وXSS. لا تقلق. لمزيد من التفاصيل، يرجى أيضًا قراءة أهدافنا الأمنية ونموذج التهديد. يرجى قراءته. حقًا. وإذا كنت تستمتع بالتفاصيل الدقيقة، فإن صفحة فئات الهجمات وتاريخ الالتفاف تفهرس حيل تحوير المحلل اللغوي، والمساحات الاسمية، والاستبدال، والقوالب التي يدافع عنها DOMPurify.

ألهم مشروع DOMPurify إنشاء HTML Sanitizer API، والذي أصبح متاحًا بالفعل في العديد من المتصفحات. يتم الآن توحيد نفس القدرة مباشرة في مواصفات WHATWG HTML.

جدول المحتويات

ماذا يفعل؟

يقوم DOMPurify بتنقية HTML ويمنع هجمات XSS. يمكنك إطعام DOMPurify على سبيل المثال سلسلة مليئة بـ HTML القذر وسيعيد سلسلة (ما لم يتم تكوينه بخلاف ذلك) تحتوي على HTML نظيف. سيقوم DOMPurify بإزالة كل ما يحتوي على HTML خطير وبالتالي يمنع هجمات XSS وغيرها من الأمور السيئة. كما أنه سريع بشكل مذهل. نستخدم التقنيات التي يوفرها المتصفح ونحولها إلى مرشح XSS. كلما كان متصفحك أسرع، كان DOMPurify أسرع.

كيف أستخدمه؟

الأمر سهل. فقط قم بتضمين DOMPurify في موقعك الإلكتروني.

استخدام النسخة غير المصغّرة (مع توفر خريطة المصدر)```html

### استخدام النسخة المصغّرة والمختبرة للإنتاج (مع توفر خريطة المصدر)```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 الناتج في عنصر DOM باستخدام innerHTML أو في DOM باستخدام document.write(). الأمر متروك لك تمامًا. لاحظ أنه افتراضيًا، نسمح بـ HTML وSVG و MathML. إذا كنت تحتاج فقط إلى HTML، وهو ما قد يكون حالة استخدام شائعة جدًا، يمكنك إعداد ذلك بسهولة أيضًا:```js const clean = DOMPurify.sanitize(dirty, { USE_PROFILES: { html: true } });

### هل توجد أي احتمالات لوجود أخطاء (Foot-guns)؟

حسنًا، يرجى ملاحظة أنه إذا قمت _أولاً_ بتنظيف HTML ثم قمت بتعديله _بعد ذلك_، فقد تُبطل بسهولة **تأثير التنظيف**. إذا قمت بتمرير الترميز المُنظّف إلى مكتبة أخرى _بعد_ التنظيف، فتأكد من أن المكتبة لا تعبث بـ HTML من تلقاء نفسها. راجع [أهداف الأمان ونموذج التهديدات](https://github.com/cure53/DOMPurify/wiki/Security-Goals-&-Threat-Model) للحصول على وصفات الاستخدام الآمن والوسوم والخصائص التي تستحق التفكير فيها مرتين، و[فئات الهجمات وتاريخ التحايل](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_ معروفة بأنها مليئة بالأخطاء بطرق تؤدي إلى XSS _حتى لو_ قام DOMPurify بكل شيء بشكل صحيح 100%. هناك **نواقل هجوم معروفة**، على سبيل المثال، في _jsdom v19.0.0_ تم إصلاحها في _jsdom v20.0.0_ - ونوصي حقًا بإبقاء _jsdom_ محدثًا بسبب ذلك.

يرجى أيضًا الانتباه إلى أن أدوات مثل [happy-dom](https://github.com/capricorn86/happy-dom) موجودة ولكنها **لا تُعتبر آمنة** في هذه المرحلة. الجمع بين DOMPurify و_happy-dom_ غير موصى به حاليًا ومن المرجح أن يؤدي إلى XSS. للحصول على خلفية حول سبب كون DOM الذي تختاره على جانب الخادم جزءًا من قاعدة الحوسبة الموثوقة لديك، راجع [فئات الهجمات وتاريخ التحايل](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

بعد ذلك، يمكنك استخدام `--output` لتحديد ملف الإخراج، و`--format` لتحديد التنسيق المطلوب (JSON أو YAML أو CSV). على سبيل المثال:

```bash
python3 tool.py --input scan_results.txt --output report.json --format json

سيقوم الأمر أعلاه بتحليل ملف scan_results.txt وإنشاء تقرير بصيغة JSON باسم report.json. إذا كنت تفضل تنسيق YAML، يمكنك تغيير قيمة --format إلى yaml.

خيارات إضافية

  • --verbose: يعرض معلومات تفصيلية أثناء عملية التحليل.
  • --quiet: يقلل من الإخراج إلى الحد الأدنى، ويعرض النتائج فقط.
  • --no-color: يعطل الألوان في الإخراج الطرفي (مفيد للبيئات التي لا تدعم ANSI).

أمثلة عملية

لتحليل ملف يحتوي على نتائج فحص متعددة وطباعة النتائج مباشرة في الطرفية:

python3 tool.py --input results.txt

لحفظ النتائج في ملف CSV مع تجاهل الألوان:

python3 tool.py --input results.txt --output results.csv --format csv --no-color

معالجة الأخطاء

إذا واجهت الأداة خطأً في قراءة الملف أو تنسيق غير صالح، ستقوم بطباعة رسالة خطأ واضحة على stderr وإرجاع رمز خروج غير صفري. يمكنك استخدام هذا السلوك في السكربتات الآلية لاكتشاف المشكلات مبكرًا.

التكامل مع أدوات أخرى

نظرًا لأن الأداة تقبل الإدخال من stdin، يمكنك استخدامها في خطوط الأنابيب (pipelines) مع أدوات أخرى مثل grep أو awk أو حتى أدوات فحص أخرى. على سبيل المثال:

cat scan_output.txt | python3 tool.py --format json | jq '.vulnerabilities[] | {id, severity}'

هذا المثال يمرر مخرجات أداة فحص أخرى إلى الأداة، ثم يحول النتائج إلى JSON، وأخيرًا يستخدم jq لاستخراج حقول محددة مثل المعرّف والخطورة.

ملاحظات حول الأداء

بالنسبة للملفات الكبيرة جدًا (أكثر من 100 ميغابايت)، قد تلاحظ زيادة في استخدام الذاكرة. إذا كنت تتعامل مع ملفات ضخمة، يُنصح بتقسيمها إلى أجزاء أصغر أو استخدام خيار --stream الذي يعالج السجلات واحدة تلو الأخرى بدلاً من تحميلها كلها في الذاكرة.

python3 tool.py --input huge_file.txt --stream --output results.json

الترخيص والمساهمات

هذه الأداة مرخصة بموجب رخصة MIT، ويمكنك استخدامها وتعديلها بحرية. إذا وجدت خطأً أو لديك اقتراح لتحسين، لا تتردد في فتح issue أو إرسال pull request على مستودع GitHub الرسمي. نرحب بجميع المساهمات التي تساعد في جعل الأداة أكثر فائدة وأمانًا للمجتمع.```js import DOMPurify from 'isomorphic-dompurify';

const clean = DOMPurify.sanitize('hello');

## هل توجد نسخة تجريبية؟

بالطبع توجد نسخة تجريبية! [جرّب DOMPurify](https://cure53.de/purify)

## ماذا لو وجدت ثغرة أمنية؟

أولاً، يرجى التواصل معنا فوراً عبر [البريد الإلكتروني](mailto:[email protected]) حتى نتمكن من العمل على إصلاحها. [مفتاح PGP](https://keyserver.ubuntu.com/pks/lookup?op=vindex&search=0xC26C858090F70ADA)

أيضاً، من المحتمل أن تكون مؤهلاً للحصول على مكافأة مقابل اكتشاف الثغرات! يستخدم الأشخاص الرائعون في [Fastmail](https://www.fastmail.com/) مكتبة DOMPurify لخدماتهم وأضافوا مكتبتنا إلى نطاق مكافآت اكتشاف الثغرات لديهم. لذا، إذا وجدت طريقة لتجاوز أو إضعاف DOMPurify، فيرجى أيضاً إلقاء نظرة على موقعهم الإلكتروني و[معلومات مكافأة اكتشاف الثغرات](https://www.fastmail.com/about/bugbounty/).

## بعض الأمثلة على التنقية من فضلك؟

كيف يبدو الترميز المنقّى؟ حسناً، [النسخة التجريبية](https://cure53.de/purify) توضح ذلك لمجموعة كبيرة من العناصر الضارة. لكن دعنا نعرض أيضاً بعض الأمثلة الأصغر!```js
DOMPurify.sanitize(''); // becomes <img src="https://raw.githubusercontent.com/cure53/dompurify/main/x">
DOMPurify.sanitize('<svg><g/onload=alert(2)//<p>'); // becomes <svg><g></g></svg>
DOMPurify.sanitize('<p>abcdef</p>'); // becomes <p>abc</p>
DOMPurify.sanitize('<math><mi//xlink:href="data:x,<script>alert(4)</script>">'); // becomes <math><mi></mi></math>
DOMPurify.sanitize('<TABLE><tr><td>HELLO</tr></TABL>'); // becomes <table><tbody><tr><td>HELLO</td></tr></tbody></table>
DOMPurify.sanitize('<UL><li><A HREF=//google.com>click</UL>'); // becomes <ul><li><a href="//google.com">click</a></li></ul>

هذه مجرد أمثلة قليلة. للحصول على التصنيف الكامل لفئات الهجمات التي تأتي منها هذه العينات - XSS الطفري، والخلط بين مساحات الأسماء، وDOM clobbering، واختراقات النص الخام، والمزيد - راجع فئات الهجمات وسجل الالتفافات.

ما الذي يتم دعمه؟

يدعم DOMPurify حالياً HTML5 وSVG وMathML. يسمح DOMPurify افتراضياً بـ CSS وسمات البيانات المخصصة في HTML. كما يدعم DOMPurify Shadow DOM - ويقوم بتعقيم قوالب DOM بشكل متكرر. يتيح لك DOMPurify أيضاً تعقيم HTML لاستخدامه مع واجهات jQuery $() وelm.html() دون أي مشاكل معروفة. للحصول على المجموعة الدقيقة من العناصر والسمات المسموح بها افتراضياً، راجع صفحة الويكي القائمة البيضاء والسوداء الافتراضية للوسوم والسمات.

ماذا عن المتصفحات القديمة مثل Internet Explorer؟

لا يقوم DOMPurify بأي شيء على الإطلاق. إنه ببساطة يعيد بالضبط السلسلة النصية التي أدخلتها إليه. يكشف DOMPurify عن خاصية تسمى isSupported، والتي تخبرك ما إذا كان سيكون قادراً على أداء مهمته، حتى تتمكن من وضع خطة احتياطية خاصة بك.

ماذا عن DOMPurify وTrusted Types؟

في الإصدار 1.0.9، تمت إضافة دعم واجهة Trusted Types API (MDN) إلى DOMPurify. في الإصدار 2.0.0، تمت إضافة علامة إعدادات للتحكم في سلوك DOMPurify فيما يتعلق بهذا الأمر.

عند استخدام DOMPurify.sanitize في بيئة تتوفر فيها واجهة Trusted Types API وتم تعيين RETURN_TRUSTED_TYPE على true، فإنه يحاول إرجاع قيمة TrustedHTML بدلاً من سلسلة نصية (لا يتغير سلوك خيارات الإعدادات RETURN_DOM وRETURN_DOM_FRAGMENT).

لاحظ أنه من أجل إنشاء سياسة في trustedTypes باستخدام DOMPurify، يلزم تعيين RETURN_TRUSTED_TYPE: false، لأن createHTML تتوقع سلسلة نصية عادية، وليس TrustedHTML. يوضح المثال أدناه ذلك.```js window.trustedTypes.createPolicy('default', { createHTML: (to_escape) => DOMPurify.sanitize(to_escape, { RETURN_TRUSTED_TYPE: false }), });

عندما لا يتم توفير `TRUSTED_TYPES_POLICY`، يحاول DOMPurify إنشاء سياسة Trusted Types داخلية خاصة به باسم `dompurify`. إذا كانت صفحتك تعرّف بالفعل سياسة خاصة بها مع CSP صارم (على سبيل المثال `trusted-types my-organization`) لا تسمح بسياسة باسم `dompurify`، فسيتم حظر هذه المحاولة من قبل المتصفح وسيتم تسجيل تحذير `TrustedTypes policy dompurify could not be created.` مع انتهاك لـ CSP.

لإيقاف DOMPurify عن إنشاء سياسته الاحتياطية الداخلية، مرّر `TRUSTED_TYPES_POLICY: null`. هذا هو الخيار الصحيح عندما تستدعي `DOMPurify.sanitize` من داخل `createHTML` الخاص بسياساتك الخاصة، ويعني أنك لست بحاجة إلى إضافة `dompurify` إلى قائمة السماح `trusted-types` في CSP الخاص بك.```js
window.trustedTypes.createPolicy('my-organization', {
  createHTML: (input) =>
    DOMPurify.sanitize(input, { TRUSTED_TYPES_POLICY: null }),
});

لا تمرر سياسة الالتفاف الخاصة بك إلى DOMPurify كسياسة TRUSTED_TYPES_POLICY الخاصة به (على سبيل المثال عبر DOMPurify.setConfig({ TRUSTED_TYPES_POLICY: myPolicy })) عندما تستدعي createHTML في تلك السياسة بالفعل DOMPurify.sanitize. هذا أمر دائري بحكم التعريف - فالتعقيم سيستدعي السياسة، والسياسة تعقّم باستدعاء DOMPurify مرة أخرى - وسيرمي DOMPurify خطأ TypeError وصفيًا لمنع التكرار اللانهائي. يجب أن تستدعي سياستك الخاصة DOMPurify؛ ولا ينبغي تكوين DOMPurify لاستدعاء سياستك.

إذا كنت تريد تطبيق نمط سياسة default هذه عبر صفحة كاملة تلقائيًا - بحيث يتم تعقيم كل مصدر HTML، بما في ذلك الكود القديم وأدوات الطرف الثالث وآلاف تعيينات innerHTML التي يصعب العثور عليها أو إعادة كتابتها - فاطّلع على DOMFortify. فهو يثبّت بالضبط سياسة Trusted Types default مدعومة بـ DOMPurify ويرفض مصادر البرامج النصية (eval، script.src، ...) بشكل قاطع. وهو مشروع منفصل عمدًا: يبقى DOMPurify معقّمًا مركّزًا، بينما يتولى DOMFortify طبقة الإنفاذ على مستوى المستند التي تقع خارج نطاق DOMPurify عمدًا.

هل يمكنني تكوين DOMPurify؟

نعم. قيم التكوين الافتراضية المضمنة جيدة جدًا بالفعل - لكن يمكنك بالطبع تجاوزها. اطّلع على مجلد /demos لترى مجموعة من الأمثلة حول كيفية تخصيص DOMPurify.

قبل توسيع قائمة السماح (ADD_TAGS، ADD_ATTR، CUSTOM_ELEMENT_HANDLING، ...) أو تخفيف إعداد افتراضي، يجدر تصفّح الوسوم والسمات التي يجب التفكير فيها مرتين - فبعضها خطير بطرق غير واضحة.

الإعدادات العامة```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 });

### التحكم في قوائم السماح وقوائم الحظر لدينا```js
// allow only <b> elements, very strict
const clean = DOMPurify.sanitize(dirty, { ALLOWED_TAGS: ['b'] });

// allow only <b> and <q> 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 <style> 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 <my-tag> 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(
  '<one attribute-one="1" attribute-two="2"></one><two attribute-one="1" attribute-two="2"></two>',
  {
    ADD_TAGS: (tagName) => {
      return Object.keys(allowlist).includes(tagName);
    },
    ADD_ATTR: (attributeName, tagName) => {
      return allowlist[tagName]?.includes(attributeName) || false;
    },
  }
); // <one attribute-one="1"></one><two attribute-two="2"></two>

// 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( '

', { 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 }, } ); //

const clean = DOMPurify.sanitize( '

', { 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 }, } ); //

const clean = DOMPurify.sanitize( '

', { 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 }, } ); //

// Example with attributeNameCheck receiving tagName as a second parameter const clean = DOMPurify.sanitize( '', { 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, }, } ); //

### سلوك التحكم المتعلق بقيم URI```js
// 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, });

### التأثير على نوع الإرجاع```js
// 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 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 elements under

elements that are removed const clean = DOMPurify.sanitize(dirty, { FORBID_CONTENTS: ['a'], FORBID_TAGS: ['p'], });

// extend the default FORBID_CONTENTS list to also remove elements under

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', });

### التأثير في المكان الذي نقوم فيه بالتنظيف```js
// 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

هناك المزيد من الأمثلة هنا، توضح كيف يمكنك تشغيل DOMPurify وتخصيصه وتهيئته ليلائم احتياجاتك.

التكوين المستمر

بدلاً من تمرير نفس التكوين مراراً وتكراراً إلى DOMPurify.sanitize، يمكنك استخدام طريقة DOMPurify.setConfig. سيستمر تكوينك حتى استدعائك التالي لـ DOMPurify.setConfig، أو حتى تقوم باستدعاء DOMPurify.clearConfig لإعادة تعيينه. تذكر أن هناك تكويناً نشطاً واحداً فقط، مما يعني أنه بمجرد تعيينه، يتم تجاهل جميع معاملات التكوين الإضافية التي يتم تمريرها إلى DOMPurify.sanitize.

الخطافات (Hooks)

يتيح لك DOMPurify توسيع وظائفه عن طريق إرفاق دالة واحدة أو أكثر باستخدام طريقة DOMPurify.addHook بأحد الخطافات التالية:

  • beforeSanitizeElements
  • uponSanitizeElement (بدون حرف 's' - يُستدعى لكل عنصر)
  • afterSanitizeElements
  • beforeSanitizeAttributes
  • uponSanitizeAttribute
  • afterSanitizeAttributes
  • beforeSanitizeShadowDOM
  • uponSanitizeShadowNode
  • afterSanitizeShadowDOM

يقوم بتمرير عقدة DOM المعالجة حالياً، وعند الحاجة حرفياً مع بيانات العقدة والسمات التي تم التحقق منها، وتكوين DOMPurify إلى دالة الاستدعاء. اطّلع على عرض توضيحي لخطاف MentalJS لترى كيف يمكن استخدام هذه الواجهة البرمجية بشكل جيد.

مثال:```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()` من داخل خطاف (hook)

**`DOMPurify.sanitize()` ليست قابلة لإعادة الدخول (re-entrant).** يُرجى عدم استدعائها من داخل خطاف، أو من دالة استدعاء إعدادات مثل `CUSTOM_ELEMENT_HANDLING.tagNameCheck` أو `attributeNameCheck`. تلك الدوال تعمل في _منتصف_ تمرير تعقيم نشط.

استدعاء `sanitize()` متداخل يعيد قراءة الإعدادات الممررة إليه، وبذلك **يستبدل الإعدادات التي لا يزال التمرير الخارجي يستخدمها**. يتم بعدها تعقيم باقي المستند الخارجي وفقًا لإعدادات الاستدعاء المتداخل بدلاً من إعداداتك. وبما أن الاستدعاء المتداخل يعمل عادةً بالإعدادات الافتراضية، فإن قائمة `ALLOWED_TAGS` الصارمة يمكن أن تتسع بصمت إلى الافتراضية في منتصف المستند، دون أي خطأ أو تحذير.

إذا كنت بحاجة إلى تعقيم ترميز متداخل، على سبيل المثال جزء HTML محمول داخل قيمة سمة، فلديك خياران آمنان. إما أن تضبط إعداداتك مرة واحدة باستخدام [`DOMPurify.setConfig`](#persistent-configuration) بدلاً من تمريرها لكل استدعاء، لأن الإعدادات الثابتة تتم مشاركتها بواسطة الاستدعاء المتداخل وتبقى سارية طوال التمرير؛ أو اجمع الأجزاء أثناء الخطاف وعقّمها باستدعاء `sanitize()` منفصل _بعد_ أن يعود الاستدعاء الخارجي.

## الإعدادات المُزالة

| الخيار | منذ | ملاحظة |
| --------------- | ----- | ------------------------ |
| SAFE_FOR_JQUERY | 2.1.0 | لا حاجة لبديل. |

## التكامل المستمر

نستخدم حاليًا GitHub Actions بالاقتران مع Playwright. يتيح لنا ذلك التأكد في كل commit أن كل شيء يعمل في المتصفحات الحديثة ذات الصلة، كما يعيد سير عمل منفصل مجدول وعند الدمج تشغيل المجموعة على لقطات محركات أقدم بحيث يتم اكتشاف الأعطال على المتصفحات القديمة أيضًا. اطّلع على سجلات البناء هنا: https://github.com/cure53/DOMPurify/actions

يمكنك أيضًا تشغيل اختبارات محلية بتنفيذ `npm run test`.

سيتم توقيع جميع الـ commits ذات الصلة بالمفتاح `0x24BB6BF4` لأمان إضافي (منذ 8 أبريل 2016).

### التطوير والمساهمة

#### التثبيت (`npm i`)

ندعم `npm` رسميًا. تم تكوين سير عمل GitHub Actions لتثبيت التبعيات باستخدام `npm`. عند استخدام إصدار قديم من `npm`، لا يمكننا ضمان إصدارات التبعيات المثبتة بشكل كامل، مما قد يؤدي إلى مشكلات غير متوقعة.

#### السكربتات

نستخدم ESLint عبر `xo` كجزء من سير عمل ما قبل الـ commit للمساعدة في ضمان اتساق الكود. بالإضافة إلى ذلك، نستخدم [Prettier](https://github.com/prettier/prettier) لتنسيق المصدر وMarkdown، ويتم بناء أصول `/dist` عبر `rollup`.

هذه هي سكربتات npm الخاصة بنا:

- `npm run dev` لبناء حزمة UMD غير مصغّرة مع مراقبة المصادر للتغييرات
- `npm run test` لفحص المصادر، وتشغيل الاختبارات عبر jsdom، وتشغيل اختبارات المتصفح في Chromium عبر Playwright
  - `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` لتشغيل تدفق اختبار CI لـ jsdom وPlaywright
  - `npm run test:fuzz` لتشغيل مُختبر صغير يغطي `sanitize()` وCONFIG
- `npm run bench` لتشغيل المعيار الصغير لـ jsdom على `dist/purify.cjs` المبني (ابنِ أولاً؛ يدعم `--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` لفحص المصادر باستخدام ESLint عبر xo
- `npm run format` لتنسيق مصادر JavaScript/TypeScript وMarkdown باستخدام Prettier
  - `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 أو مخصصة لتكون "خاصة" على سبيل المثال لتعديل ملفات توزيع البناء مع كل commit.

## القائمة البريدية الأمنية

نحتفظ بقائمة بريدية تُشعر كلما تم نشر إصدار **حرج أمنيًا** من DOMPurify. هذا يعني، إذا وجد شخص ما تجاوزًا وأصلحناه بإصدار (وهو ما يحدث دائمًا عند العثور على تجاوز)، سيتم إرسال بريد إلى تلك القائمة. يحدث هذا عادةً خلال دقائق أو بضع ساعات بعد معرفة التجاوز. يمكن الاشتراك في القائمة هنا:

[https://lists.ruhr-uni-bochum.de/mailman/listinfo/dompurify-security](https://lists.ruhr-uni-bochum.de/mailman/listinfo/dompurify-security)

لن يتم الإعلان عن إصدارات الميزات إلى هذه القائمة.

## من ساهم؟

ساعد العديد من الأشخاص DOMPurify ليصبح ما هو عليه اليوم، وهم يستحقون التقدير!

[gnyselcuk](https://github.com/gnyselcuk), [leechristensen](https://github.com/leechristensen),[offset](https://github.com/offset), [Bankde](https://github.com/Bankde), [lukewarlow](https://github.com/lukewarlow), [DEMON1A](https://github.com/DEMON1A), [fg0x0](https://github.com/fg0x0), [kodareef5](https://github.com/kodareef5), [DavidOliver](https://github.com/DavidOliver), [1Jesper1](https://github.com/1Jesper1), [bencalif](https://github.com/bencalif), [trace37labs](https://github.com/trace37labs), [eddieran](https://github.com/eddieran), [christos-eth](https://github.com/christos-eth), [researchatfluidattacks](https://github.com/researchatfluidattacks), [frevadiscor](https://github.com/frevadiscor), [Rotzbua](https://github.com/Rotzbua), [binhpv](https://github.com/binhpv), [MariusRumpf](https://github.com/MariusRumpf), [prasadrajandran](https://github.com/prasadrajandran), [Cybozu 💛💸](https://github.com/cybozu), [hata6502 💸](https://github.com/hata6502), [openclaw 💸](https://github.com/openclaw), [intra-mart-dh 💸](https://github.com/intra-mart-dh), [nelstrom ❤️](https://github.com/nelstrom), [hash_kitten ❤️](https://twitter.com/hash_kitten), [kevin_mizu ❤️](https://twitter.com/kevin_mizu), [icesfont ❤️](https://github.com/icesfont), [reduckted ❤️](https://github.com/reduckted), [dcramer 💸](https://github.com/dcramer), [JGraph 💸](https://github.com/jgraph), [baekilda 💸](https://github.com/baekilda), [Healthchecks 💸](https://github.com/healthchecks), [Sentry 💸](https://github.com/getsentry), [jarrodldavis 💸](https://github.com/jarrodldavis), [CynegeticIO](https://github.com/CynegeticIO), [ssi02014 ❤️](https://github.com/ssi02014), [GrantGryczan](https://github.com/GrantGryczan), [Lowdefy](https://twitter.com/lowdefy), [granlem](https://twitter.com/MaximeVeit), [oreoshake](https://github.com/oreoshake), [tdeekens ❤️](https://github.com/tdeekens), [peernohell ❤️](https://github.com/peernohell), [is2ei](https://github.com/is2ei), [SoheilKhodayari](https://github.com/SoheilKhodayari), [franktopel](https://github.com/franktopel), [NateScarlet](https://github.com/NateScarlet), [neilj](https://github.com/neilj), [fhemberger](https://github.com/fhemberger), [Joris-van-der-Wel](https://github.com/Joris-van-der-Wel), [ydaniv](https://github.com/ydaniv), [terjanq](https://twitter.com/terjanq), [filedescriptor](https://github.com/filedescriptor), [ConradIrwin](https://github.com/ConradIrwin), [gibson042](https://github.com/gibson042), [choumx](https://github.com/choumx), [0xSobky](https://github.com/0xSobky), [styfle](https://github.com/styfle), [koto](https://github.com/koto), [tlau88](https://github.com/tlau88), [strugee](https://github.com/strugee), [oparoz](https://github.com/oparoz), [mathiasbynens](https://github.com/mathiasbynens), [edg2s](https://github.com/edg2s), [dnkolegov](https://github.com/dnkolegov), [dhardtke](https://github.com/dhardtke), [wirehead](https://github.com/wirehead), [thorn0](https://github.com/thorn0), [styu](https://github.com/styu), [mozfreddyb ❤️](https://github.com/mozfreddyb), [mikesamuel](https://github.com/mikesamuel), [jorangreef](https://github.com/jorangreef), [jimmyhchan](https://github.com/jimmyhchan), [jameydeorio](https://github.com/jameydeorio), [jameskraus](https://github.com/jameskraus), [hyderali](https://github.com/hyderali), [hansottowirtz](https://github.com/hansottowirtz), [hackvertor](https://github.com/hackvertor), [freddyb](https://github.com/freddyb), [flavorjones](https://github.com/flavorjones), [djfarrelly](https://github.com/djfarrelly), [devd](https://github.com/devd), [camerondunford](https://github.com/camerondunford), [buu700](https://github.com/buu700), [buildog](https://github.com/buildog), [alabiaga](https://github.com/alabiaga), [Vector919](https://github.com/Vector919), [Robbert](https://github.com/Robbert), [GreLI](https://github.com/GreLI), [FuzzySockets](https://github.com/FuzzySockets), [ArtemBernatskyy](https://github.com/ArtemBernatskyy), [@garethheyes](https://twitter.com/garethheyes), [@shafigullin](https://twitter.com/shafigullin), [@mmrupp](https://twitter.com/mmrupp), [@irsdl](https://twitter.com/irsdl),[ShikariSenpai](https://github.com/ShikariSenpai), [ansjdnakjdnajkd](https://github.com/ansjdnakjdnajkd), [@asutherland](https://twitter.com/asutherland), [@mathias](https://twitter.com/mathias), [@cgvwzq](https://twitter.com/cgvwzq), [@robbertatwork](https://twitter.com/robbertatwork), [@giutro](https://twitter.com/giutro), [@CmdEngineer\_](https://twitter.com/CmdEngineer_), [@avr4mit](https://twitter.com/avr4mit), [davecardwell](https://github.com/davecardwell), [Develop-KIM](https://github.com/Develop-KIM), [asamuzaK](https://github.com/asamuzaK), [fishjojo1 ❤️](https://github.com/fishjojo1), [Rikuxx0](https://github.com/Rikuxx0), [donmccurdy](https://github.com/donmccurdy), [hhk-png](https://github.com/hhk-png), [elrion018](https://github.com/elrion018), [michalnieruchalski-tiugo](https://github.com/michalnieruchalski-tiugo), [reey](https://github.com/reey), [KanhaKanhaiya](https://github.com/KanhaKanhaiya), [odaysec](https://github.com/odaysec), [Akokonunes](https://github.com/Akokonunes), [alirezarouhbakhsh](https://github.com/alirezarouhbakhsh), [Jaybhade](https://github.com/Jaybhade) وخاصة [@securitymb ❤️](https://twitter.com/securitymb) و [@masatokinugawa ❤️](https://twitter.com/masatokinugawa)

الفئات