> ## Content Index
> Fetch the complete content index at: https://arabroot.io/llms.txt
> Use this file to discover other available public pages before exploring further.

# أي ثغرة تصلح أولاً؟ ترتيب الأولوية Prioritization بلغة بسيطة
- URL: https://arabroot.io/articles/اي-ثغرة-تصلح-اولا-ترتيب-اولوية-الثغرات-cvss-epss-kev/
- Published: 2026-10-28T08:43:25.000Z
- Updated: 2026-10-28T09:43:14.000Z
- Description: فحصنا ثلاث Containers فظهرت 5025 نتيجة، فرتبناها بالتقييم CVSS واحتمال الاستغلال EPSS وقائمة KEV لنعرف ما يصلح هذا الأسبوع.
- Author: فريق عرب رووت
- Tags: الأدلة التقنية, الأمن السيبراني, Docker والحاويات, الاستضافة الذاتية, Trivy

تشغل أداة فحص الثغرات Vulnerability Scanner على ثلاث Containers صغيرة، فترجع لك بخمسة آلاف سطر. وفي كل سطر رقم ثغرة CVE واسم حزمة Package وكلمة HIGH أو CRITICAL بلون أحمر، وأمامك أسبوع عمل واحد وفريق من شخصين. والسؤال الذي يقف عنده أغلب من بدأ إدارة الثغرات Vulnerability Management ليس «هل عندي ثغرات؟»، فالإجابة نعم دائماً، وإنما «بأي ثغرة أبدأ، وما الذي أتركه بضمير مرتاح إلى دورة التحديث العادية؟».

وهذا ليس سؤالاً نظرياً، فيوم 27 أكتوبر 2026 أضافت وكالة CISA الأمريكية ثغرة في مكتبة الضغط Brotli من Google إلى قائمة الثغرات المستغلة فعلاً KEV، والثغرة نفسها كانت موجودة في اثنتين من الـ Containers الثلاث التي فحصناها لهذا المقال. ولكنها لم تكن في رأس القائمة عند من رتب بالخطورة، فقد عرضها الفاحص بخطورة HIGH مثل 633 نتيجة أخرى، بينما كانت هناك 36 نتيجة بخطورة CRITICAL فوقها، ولا واحدة من هذه الحرجة كانت في KEV. وفي هذا المقال سوف نأخذ نتائج الفحص الحقيقية، ونرتبها بأربع طرق مختلفة، ونرى كم بنداً تضع كل طريقة أمام الفريق، ولماذا.

وقد شرحنا في [مقال إدارة الثغرات](https://arabroot.io/articles/%D8%A7%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%AB%D8%BA%D8%B1%D8%A7%D8%AA-vulnerability-management-%D9%84%D8%B3%D9%8A%D8%B1%D9%81%D8%B1%D8%A7%D8%AA%D9%83/) معنى CVE ودورة الإدارة كاملة، وعرفنا فيه بالإشارات الثلاث تعريفاً سريعاً، وفي [مقال أدوات إدارة الثغرات](https://arabroot.io/articles/%D8%A7%D8%AF%D9%88%D8%A7%D8%AA-%D8%A7%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%AB%D8%BA%D8%B1%D8%A7%D8%AA-%D9%85%D9%81%D8%AA%D9%88%D8%AD%D8%A9-%D8%A7%D9%84%D9%85%D8%B5%D8%AF%D8%B1/) قارنا الفاحصات نفسها. أما هنا فنفتح كل إشارة من الداخل: كيف تحسب، وماذا تقيس بالضبط، ومتى تخدعك، ثم نبني منها سياسة مكتوبة يتفق عليها الفريق.

[![](https://arabroot.io/content/images/2026/10/vuln-management-cover-cover.webp)دليلإدارة الثغرات Vulnerability Management: هل سيرفرك متأثر؟كيف تعرف خلال ساعات أن ثغرة جديدة تمس سيرفراتك، ولماذا يخدعك رقم الإصدار، وكيف ترتب الإصلاح وتتأكد أنه تم فعلاً.](https://arabroot.io/articles/%D8%A7%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%AB%D8%BA%D8%B1%D8%A7%D8%AA-vulnerability-management-%D9%84%D8%B3%D9%8A%D8%B1%D9%81%D8%B1%D8%A7%D8%AA%D9%83/)[![](https://arabroot.io/content/images/2026/10/vuln-tools-cover-cover.webp)دليلأدوات إدارة الثغرات Vulnerability Management مفتوحة المصدرأي أداة مفتوحة المصدر تجرد سيرفراتك وتطابقها مع الثغرات وتنبهك بالجديد، وماذا رأى Trivy وGrype فعلاً في ثغرات أكتوبر.](https://arabroot.io/articles/%D8%A7%D8%AF%D9%88%D8%A7%D8%AA-%D8%A7%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%AB%D8%BA%D8%B1%D8%A7%D8%AA-%D9%85%D9%81%D8%AA%D9%88%D8%AD%D8%A9-%D8%A7%D9%84%D9%85%D8%B5%D8%AF%D8%B1/)[![](https://arabroot.io/content/images/2026/10/vuln-lab-cover-cover.webp)دليلمختبر Lab: اكتشف السيرفرات المتأثرة بثغرة CVE جديدة وأصلحهافحصنا ثلاثة سيرفرات قديمة وسيرفراً محدثاً بأدوات Trivy وWazuh وسكربت تنبيه صغير، فظهر من يكتشف ثغرة الأسبوع ومن يفوته.](https://arabroot.io/articles/%D9%85%D8%AE%D8%AA%D8%A8%D8%B1-%D8%A7%D9%83%D8%AA%D8%B4%D8%A7%D9%81-%D8%A7%D9%84%D8%B3%D9%8A%D8%B1%D9%81%D8%B1%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%AA%D8%A7%D8%AB%D8%B1%D8%A9-%D8%A8%D8%AB%D8%BA%D8%B1%D8%A9-cve-%D9%88%D8%A7%D8%B5%D9%84%D8%A7%D8%AD%D9%87%D8%A7/)

وسوف نناقش في هذا المقال ما يلي:

- لماذا لا تستطيع إصلاح كل شيء، ولماذا يفشل الحل البسيط «أصلح الحرج والعالي أولاً».
- التقييم CVSS من الداخل: ماذا يقيس الرقم، ومن يكتبه، ولماذا يختلف بين المورد والتوزيعة، وما الذي أضافه الإصدار 4.0.
- احتمال الاستغلال EPSS: من أين يأتي الرقم، والفرق بين الاحتمال Probability والمئين Percentile، وكيف تجمع الاحتمالات.
- قائمة KEV: شروط دخولها، وحقولها، والتوجيه BOD 26-04 الذي حل محل BOD 22-01 في يونيو 2026.
- من الرقم إلى القرار: شجرة SSVC، وجدول BOD 26-04، والسياق الذي لا تعرفه أي قاعدة بيانات.
- تجربة عملية: نفحص ثلاث Containers بأداة Trivy، ونربط النتائج بقائمة KEV وبيانات EPSS وإجابات CISA، ونقارن السياسات بالأرقام.
- تجربتان «ماذا لو»: ماذا يحدث إذا عاملت الثغرة المجهولة كأسوأ حال أو كأفضل حال، وماذا يحدث إذا غيرت ال Image بدل أن ترتب نتائجها.
- سياسة مكتوبة لشركة صغيرة، وأخطاء شائعة، وقائمة تحقق.

## لماذا لا تستطيع إصلاح كل شيء؟

لنفرض أن لديك متجراً إلكترونياً صغيراً يعمل على ثلاث Containers: `edge-nginx` وهو ال Reverse Proxy المفتوح للإنترنت على المنفذ 443، و`shop-api` وهو تطبيق Node.js الذي يستقبل طلبات العملاء عبر ال Proxy، و`shop-db` وهو قاعدة بيانات MariaDB على الشبكة الداخلية فقط. هذه ليست شركة متخيلة بقدر ما هي أبسط شكل لأي خدمة ويب، وال Images الثلاث في المختبر رسمية من Docker Hub بنفس الإصدارات التي يستخدمها كثيرون اليوم. وعندما فحصناها يوم 28 أكتوبر 2026 خرجت 5025 نتيجة، فيها 2607 معرف ثغرة مختلف.

والطريقة الأولى التي يفكر فيها أي فريق هي أن يصلح كل شيء، وهذه الطريقة تفشل قبل أن تبدأ، والسبب أن أغلب النتائج لا يوجد لها إصلاح أصلاً. ففي `shop-api` وحده 4871 نتيجة، منها 436 فقط لها إصدار مصلح متاح الآن، والبقية بحالة `affected` أي أن التوزيعة تعرف الثغرة ولم تصدر إصلاحاً، أو `fix_deferred` أي أنها أجلت الإصلاح إلى تحديث قادم لأن الخطورة عندها منخفضة، أو `will_not_fix` أي أنها قررت ألا تصلحها في هذا الإصدار من التوزيعة. وهذه الحالات ليست اختراعاً من الفاحص، وإنما من قاعدة بيانات Debian الأمنية نفسها، ويعرضها Trivy كما شرحت [صفحة التصفية في توثيقه](https://trivy.dev/docs/v0.76/guide/configuration/filtering/?ref=arabroot.io).

والطريقة الثانية هي التي تجدها في أغلب السياسات المكتوبة: أصلح الحرج Critical خلال أسبوع والعالي High خلال شهر. وهي أفضل من الأولى بكثير، ولكنها في المختبر وضعت أمام الفريق 672 نتيجة في 330 ثغرة، وفيها مشكلتان. الأولى أن الخطورة تقيس ما يمكن أن يحدث لا ما يحدث، فمن 14 ثغرة حرجة في الفحص كانت 11 باحتمال استغلال أقل من 1%، ولم تكن واحدة منها في قائمة KEV. والثانية أن الثغرة الوحيدة المستغلة فعلاً، ثغرة Brotli، لم تكن حرجة في تقرير الفاحص أصلاً، وإنما عالية، أي أنها ضاعت وسط 633 نتيجة أخرى بنفس الكلمة.

وقد يتساءل البعض: هل المشكلة في كثرة النتائج فقط؟ لا، فالمشكلة أن الاستغلال نفسه نادر. فبحسب [الأسئلة الشائعة في موقع EPSS](https://www.first.org/epss/faq?ref=arabroot.io) فإن قائمة KEV تضم نحو 0.5% من كل ثغرات CVE المنشورة، وفي أي ثلاثين يوماً يرصد شركاء بيانات EPSS نشاط استغلال لنحو 2.5% إلى 3% منها فقط. وهذا يعني أن أغلب ما في تقريرك لن يستغله أحد في الشهر القادم، والقلة التي ستستغل هي التي يجب أن تجدها، وهذا بالضبط ما يحاول ترتيب الأولوية Prioritization أن يفعله.

![أربع لوحات: التقييم CVSS وسؤاله ما أسوأ ما يحدث وقيمته 9.2 لثغرة Brotli من Google بينما عرضها Trivy بخطورة HIGH، واحتمال الاستغلال EPSS وسؤاله ما احتمال رصد الاستغلال خلال 30 يوماً وقيمته 0.555 يوم 27 أكتوبر بعد أن كان 0.0048 يوم 23 أكتوبر، وقائمة KEV وسؤالها هل يوجد دليل على الاستغلال وإجابتها نعم منذ 27 أكتوبر وموعد إصلاحها 10 نوفمبر، والسياق وسؤاله أين تعمل الحزمة ومن يصل إليها وأهمية النظام للحاويات الثلاث edge-nginx وshop-api وshop-db](https://arabroot.io/content/images/2026/10/vuln-prioritization-01-signals.webp)

ثلاثة أسئلة تجيب عنها مصادر عامة، والرابع لا يجيب عنه أحد غيرك

والصورة أعلاه تلخص بقية المقال: كل إشارة تجيب عن سؤال مختلف، ولا يوجد رقم واحد يجمعها كلها. فالتقييم CVSS يقول ما أسوأ ما يمكن أن يحدث، واحتمال EPSS يقول ما احتمال أن يحدث قريباً، وقائمة KEV تقول إنه يحدث الآن، والسياق يقول هل يحدث عندك أنت. وسوف نأخذها بالترتيب، ثم نجمعها في التجربة العملية.

## التقييم CVSS من الداخل: ماذا يقيس الرقم؟

نظام تقييم الثغرات CVSS (Common Vulnerability Scoring System) بدأ في 2005، وتديره اليوم منظمة FIRST، وآخر إصداراته 4.0 الذي [نشرته في نوفمبر 2023](https://www.first.org/cvss/?ref=arabroot.io). والفكرة الأساسية فيه أن تصف الثغرة بمجموعة أسئلة ثابتة، لكل سؤال إجابات محددة، ثم تحول الإجابات إلى رقم من 0 إلى 10 بمعادلة منشورة، فيحصل كل من يقرأ نفس الوصف على نفس الرقم. وهذا ما جعله لغة مشتركة بين الموردين والتوزيعات والفاحصات: عندما يقول المورد 9.8 يفهم الجميع تقريباً ما يقصد.

### الرقم يأتي من وصف Vector، والوصف أهم من الرقم

لا تقرأ الرقم وحده، وإنما اقرأ الوصف Vector String الذي جاء منه، لأن الرقم يجمع إجابات مختلفة جداً في قيمة واحدة. وهذا وصف ثغرة Brotli كما نشرته Google في سجل CVE:

```text
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
```

وفي الوصف أعلاه لاحظ التالي:

- **طريق الهجوم AV:N:** عبر الشبكة Network، أي أن المهاجم لا يحتاج أن يكون على نفس الجهاز أو نفس الشبكة المحلية.
- **تعقيد الهجوم AC:L:** منخفض، فلا توجد حماية خاصة يجب تجاوزها.
- **متطلبات الهجوم AT:P:** موجودة Present، وهذا سؤال جديد في الإصدار 4.0، ويعني أن نجاح الهجوم يعتمد على ظرف في طريقة تشغيل النظام المصاب لا يتحكم فيه المهاجم، ولا يذكر سجل CVE ما هذا الظرف بالضبط، وهذا مثال على أن الوصف يجيب عن أسئلة ولا يشرح أسبابها.
- **الصلاحيات PR:N والتفاعل UI:N:** لا يحتاج حساباً ولا ضغطة من مستخدم، وهذان السؤالان مع AV:N هما ما يجعل الثغرة قابلة للاستغلال الآلي على نطاق واسع.
- **الأثر على النظام المصاب VC:H/VI:H/VA:H:** عال في السرية والسلامة والتوافر، والأثر على الأنظمة التالية SC/SI/SA لا يوجد.

والرقم الناتج 9.2، أي حرجة Critical. ولكن Trivy عرضها لنا بخطورة HIGH، والسبب أنه يأخذ الخطورة من مصدر بيانات التوزيعة قبل NVD، كما يشرح [توثيق Trivy في قسم اختيار الخطورة](https://trivy.dev/docs/v0.76/guide/scanner/vulnerability/?ref=arabroot.io)، لأن التوزيعة تعرف كيف بنت الحزمة وما الإعداد الافتراضي فيها. وهذا منطقي في أغلب الحالات، ولكنه يعني أن كلمة HIGH في تقريرك قد تكون رأي Alpine أو Debian، وأن كلمة CRITICAL قد تكون رأي NVD أو المورد، وأنك عندما ترتب بعمود الخطورة فأنت تخلط مصادر مختلفة في عمود واحد دون أن تعرف.

### أربع مجموعات، والرقم الذي تراه هو الأولى فقط

يقسم الإصدار 4.0 الأسئلة إلى أربع مجموعات، كما في [مواصفة CVSS 4.0](https://www.first.org/cvss/v4.0/specification-document?ref=arabroot.io)، ويطلب أن تكتب بجانب كل رقم أي المجموعات دخلت فيه: CVSS-B للأساسية وحدها، وCVSS-BT للأساسية مع التهديد، وCVSS-BE للأساسية مع البيئة، وCVSS-BTE للثلاث. والصورة التالية تبينها مع أرقام حقيقية حسبناها لنفس الثغرة:

![أربع لوحات: المقاييس الأساسية Base يكتبها المورد وقيمتها 9.2، ومقاييس التهديد Threat ونضج الاستغلال فيها يخفض الرقم إلى 7.2 إذا لم يعرف أي استغلال، ومقاييس البيئة Environmental يملؤها صاحب النظام فتعطي بين 7.5 و9.2، والمقاييس الإضافية Supplemental مثل Automatable وSafety لا تدخل في الحساب](https://arabroot.io/content/images/2026/10/vuln-prioritization-03-cvss.webp)

النشرة والفاحص يعطيانك CVSS-B، أما الرقم الذي يخصك فهو CVSS-BTE ولا يكتبه أحد غيرك

- **الأساسية Base:** صفات الثغرة نفسها التي لا تتغير بمرور الوقت ولا باختلاف البيئة، ويكتبها المورد أو من يصدر رقم CVE.
- **التهديد Threat:** سؤال واحد هو نضج الاستغلال Exploit Maturity، وإجاباته: هوجمت Attacked، أو يوجد إثبات مفهوم PoC، أو لا يعرف أي استغلال Unreported.
- **البيئة Environmental:** أهمية السرية والسلامة والتوافر لهذا النظام عندك، ونسخة معدلة من كل سؤال أساسي تجيب عنها بعد أن تحسب الحماية التي وضعتها، مثل أن السيرفر لا يصل إليه أحد من خارج الشبكة.
- **الإضافية Supplemental:** معلومات لا تدخل في المعادلة، مثل هل يمكن أتمتة الاستغلال Automatable، وهل يمس السلامة البدنية Safety، وكم جهداً يحتاج الإصلاح.

وهنا تفصيل مهم يقع فيه كثيرون: القيمة الافتراضية لنضج الاستغلال هي «غير محدد» Not Defined، والمواصفة تقول صراحة إنها تعامل في الحساب كأنها «هوجمت» Attacked، أي أسوأ حال. وهذا يعني أن مجموعة التهديد لا ترفع الرقم أبداً، وإنما تخفضه عندما تعرف أن أحداً لم يستغل الثغرة بعد. لذلك فإن رقم 9.2 الذي تراه في النشرة هو في الحقيقة افتراض أن الثغرة تستغل الآن.

### ماذا يحدث للرقم إذا أجبت عن أسئلة البيئة؟

لكي ترى أثر كل مجموعة بالأرقام لا بالكلام، كتبنا سكربتاً صغيراً يحسب الرقم بمكتبة `cvss` التي تطبق معادلة الإصدار 4.0، ويأخذ الوصف الأساسي لثغرة Brotli ويضيف إليه إجابات مختلفة:

```python
"""Scores one CVSS 4.0 base vector with different Threat and Environmental answers (FIRST CVSS v4.0 math via the cvss package)."""
from cvss import CVSS4
base = "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N"     # CVE-2026-111497, from the Google CNA
cases = [("base only (what the CNA published)", ""),
         ("threat: exploitation reported (E:A)", "/E:A"),
         ("threat: no PoC known yet (E:U)", "/E:U"),
         ("internal DB server, not reachable from outside (MAV:A)", "/E:A/MAV:A"),
         ("only an administrator can feed it data (MPR:H)", "/E:A/MPR:H"),
         ("public proxy holding customer data (CR:H IR:H AR:H)", "/E:A/CR:H/IR:H/AR:H"),
         ("test container, nothing important (CR:L IR:L AR:L)", "/E:A/CR:L/IR:L/AR:L")]
for name, extra in cases:
    c = CVSS4(base + extra)
    print(f"{c.base_score:>4}  {c.severity:8}  {name:58} {extra or '-'}")
```

```bash
docker run --rm -v "$(pwd -W):/w" -w /w python:3.13.17-slim sh -c "pip install -q cvss==3.6 && python cvss4.py"
```

والمخرج سوف يكون كما يلي:

```text
 9.2  Critical  base only (what the CNA published)                         -
 9.2  Critical  threat: exploitation reported (E:A)                        /E:A
 7.2  High      threat: no PoC known yet (E:U)                             /E:U
 7.7  High      internal DB server, not reachable from outside (MAV:A)     /E:A/MAV:A
 7.5  High      only an administrator can feed it data (MPR:H)             /E:A/MPR:H
 9.2  Critical  public proxy holding customer data (CR:H IR:H AR:H)        /E:A/CR:H/IR:H/AR:H
 7.9  High      test container, nothing important (CR:L IR:L AR:L)         /E:A/CR:L/IR:L/AR:L
```

في المخرج أعلاه لاحظ التالي:

- إضافة `E:A` لم تغير شيئاً، لأن الرقم الأساسي كان يفترضها أصلاً كما شرحنا.
- لو لم يكن هناك أي استغلال معروف `E:U` لنزلت الثغرة من حرجة إلى عالية بـ 7.2، وهذا ما كان صحيحاً يوم 22 أكتوبر قبل أن تقول CISA إن الاستغلال نشط.
- نفس الثغرة على قاعدة البيانات الداخلية `MAV:A`، أي أن الوصول إليها من الشبكة المجاورة فقط، تعطي 7.7، وعلى Container اختبار لا يحمل شيئاً مهماً تعطي 7.9، أما على ال Proxy المفتوح الذي يحمل بيانات العملاء فتبقى 9.2.
- الفرق بين أعلى رقم وأدناه أقل من نقطتين، فالبيئة تحرك الرقم ولكنها لا تقلبه، ولذلك لا يكفي CVSS وحده حتى بعد أن تملأ كل أسئلته، فهو يبقى سؤالاً عن الخطورة لا عن الاحتمال.

وفي الواقع قليلون من يملؤون أسئلة البيئة لكل ثغرة، لأن ذلك يحتاج أن تعرف كل نظام بالتفصيل، وهذا عمل لا ينتهي مع آلاف النتائج. لذلك فالاستخدام العملي لهذه المجموعة أن تحدد أهمية السرية والسلامة والتوافر مرة واحدة لكل نظام في ملف الأصول Asset Inventory، ثم تترك الأداة تطبقها، وأن تبقي التعديل اليدوي للثغرات القليلة التي وصلت فعلاً إلى رأس القائمة.

## احتمال الاستغلال EPSS: من أين يأتي الرقم؟

إذا كان CVSS يقيس ما يمكن أن يحدث، فإن نظام توقع الاستغلال EPSS (Exploit Prediction Scoring System) يحاول أن يقيس ما سوف يحدث. وقد بدأ كبحث أكاديمي، ثم أصبحت له مجموعة اهتمام خاصة SIG في منظمة FIRST، وتنشر بياناته شركة Empirical Security مجاناً كل يوم. وأول نسخة من الأرقام نشرت في أبريل 2021، وصدرت من النموذج Model منذ ذلك الوقت خمس نسخ، وآخرها النسخة الخامسة `v2026.06.15` التي بدأ نشرها في 15 يونيو 2026، كما في [صفحة البيانات](https://www.first.org/epss/data?ref=arabroot.io). وهذا تفصيل مهم إذا رسمت تاريخ رقم ثغرة على مدى طويل، فالقفزة في يوم تغيير النموذج سببها تغيير الطريقة لا تغيير الثغرة.

### ما الذي يتعلم منه النموذج؟

بحسب [صفحة طريقة العمل](https://www.first.org/epss/how-it-works?ref=arabroot.io) يبنى سجل كل ثغرة في كل يوم من نحو 2850 خاصية Feature، ويمكن تقسيمها إلى أربع عائلات:

- **كود الاستغلال والأدوات:** هل يوجد كود استغلال منشور، وأين، وهل دخل في أداة هجوم جاهزة، وهل أضيفت الثغرة إلى قوالب Nuclei أو إلى محركات البحث عن الأجهزة المكشوفة. وكود مجرب داخل إطار هجوم معروف أثقل في الحساب من إثبات مفهوم منشور في مدونة شخصية.
- **الحديث عن الثغرة:** أي المواقع الأمنية تذكرها، ومتى آخر مرة، من نشرات الموردين والتوزيعات إلى منصات رصد الإنترنت.
- **صفات الثغرة:** أسئلة CVSS نفسها كل واحد على حدة لا الرقم النهائي، ووسوم مستخرجة من الوصف مثل «تنفيذ كود عن بعد»، واسم المورد والمنتج.
- **العمر وعدد المراجع:** وهنا المفاجأة التي تذكرها الصفحة نفسها، فالثغرات الأقدم من سنتين تستغل بنحو خمسة أضعاف معدل الثغرات التي عمرها أقل من شهر.

أما ما يتعلم النموذج أن يتوقعه فهو نشاط الاستغلال الذي يرصده قرابة اثني عشر شريكاً من شركاء البيانات: برامج مكافحة الفيروسات على الأجهزة، ومصائد المهاجمين Honeypots، وأنظمة كشف ومنع التسلل IDS/IPS، وقوائم الاستغلال المنشورة. ولاحظ أن ما يرصد هو المحاولة لا النجاح، فطلب استغلال منعه جهاز IPS يعد نشاطاً لأنه يدل على أن مهاجماً قرر أن يستهدف هذه الثغرة.

### الاحتمال والمئين: لا تخلط بينهما

كل ثغرة لها رقمان في بيانات EPSS. الأول هو الاحتمال Probability، وهو رقم من 0 إلى 1 يعني احتمال أن يرصد نشاط استغلال لها خلال الثلاثين يوماً القادمة، فإذا أخذت مئة ثغرة رقم كل واحدة منها 0.05 فالمتوقع أن يرصد استغلال خمس منها في الشهر القادم. والثاني هو المئين Percentile، أي ترتيب الثغرة بين كل الثغرات، فالمئين 0.990 يعني أن رقمها أعلى من 99% من كل الثغرات المسجلة.

وقد يتساءل البعض: لماذا تبدو كل الاحتمالات صغيرة؟ والإجابة أن الاستغلال نادر كما ذكرنا، فالنموذج الصادق يجب أن يعطي أغلب الثغرات أرقاماً قريبة من الصفر. لذلك تقول [صفحة الأسئلة الشائعة](https://www.first.org/epss/faq?ref=arabroot.io) إن احتمال 0.10 يقع اليوم عند المئين 95 تقريباً، أي أن 10% تبدو قليلة ولكنها أعلى من 95% من كل الثغرات. والخطأ الشائع هنا أن تختار حداً بالمئين مثل «كل ما فوق المئين 90» وتظن أنه حد صغير، والحقيقة أنه يشمل عشرات الآلاف من الثغرات التي احتمال كل واحدة منها أقل من 5%.

### الرقم يتغير كل يوم، وهذه ميزة

لأن الرقم يحسب كل يوم من جديد فإنه يتحرك مع ما يحدث في العالم، والصورة التالية تبين ما حدث لثغرة Brotli في ستة أيام، بالأرقام الحقيقية من واجهة EPSS البرمجية API:

![خط زمني من 21 إلى 27 أكتوبر 2026: إصدار Brotli 1.2.1 يغلق الثغرة في 21 أكتوبر، ونشر CVE من Google بتقييم CVSS 4.0 بقيمة 9.2 في 22 أكتوبر، وإجابات CISA Vulnrichment بأن الاستغلال نشط في 23 أكتوبر، وقيم EPSS اليومية 0.0048 ثم 0.0071 ثم قفزة إلى 0.328 في 25 أكتوبر ثم 0.360 ثم 0.555 في 27 أكتوبر يوم إضافتها إلى KEV بموعد إصلاح 10 نوفمبر](https://arabroot.io/content/images/2026/10/vuln-prioritization-02-timeline.webp)

الإصلاح سبق الجميع، وCISA قالت «نشط» قبل KEV بأربعة أيام، وEPSS قفز قبل KEV بيومين

```bash
curl -s "https://api.first.org/data/v1/epss?cve=CVE-2026-111497&scope=time-series"
```

```text
"epss": "0.554830000", "percentile": "0.990300000", "date": "2026-10-27",
"time-series": [
  {"epss": "0.360270000", "percentile": "0.984630000", "date": "2026-10-26"},
  {"epss": "0.32782000",  "percentile": "0.98336000",  "date": "2026-10-25"},
  {"epss": "0.00710000",  "percentile": "0.53063000",  "date": "2026-10-24"},
  {"epss": "0.00480000",  "percentile": "0.40511000",  "date": "2026-10-23"}]
```

والمخرج أعلاه مختصر من رد ال API، وفيه درس مهم: في اليوم الأول بعد النشر كان احتمال الثغرة 0.0048، أي أقل من نصف في المئة، وكانت تحت نصف الثغرات المسجلة في الترتيب. فمن رتب بـ EPSS يوم 23 أكتوبر وضعها في آخر القائمة، ومن رتب يوم 25 وضعها في أعلى 2% من كل الثغرات. لذلك فإن EPSS إشارة تأتي متأخرة بطبيعتها في الأيام الأولى، لأنها تعتمد على ما يرصد من نشاط ومن حديث، ولا تصلح وحدها لثغرة عمرها يوم.

💡

نشر فريق EPSS [تحليلاً لما رآه النموذج في ثغرة Log4Shell](https://www.first.org/epss/articles/log4shell?ref=arabroot.io) في ديسمبر 2021: نشر رقم CVE يوم 10 ديسمبر، وكان الاحتمال 0.355 في اليوم التالي، ثم 0.30 يوم 14 ديسمبر بعد أن عدل الوصف وحذفت منه كلمة «remote»، ثم 0.633 بعد نشر كود الاستغلال، ثم 0.944 يوم 17 ديسمبر عندما أضيفت وحدة فحص لها في Metasploit. ويقول كاتب التحليل نفسه إن ثغرة بهذا الحجم لا تحتاج أي نظام تقييم لتعرف أنها خطيرة، وإن قيمة EPSS الحقيقية في آلاف الثغرات التي لا يتكلم عنها أحد.

### كم ثغرة يتوقع أن تستغل من تقريرك كله؟

لأن الرقم احتمال حقيقي يمكن أن تجمعه، و[صفحة استخدام EPSS](https://www.first.org/epss/using-epss?ref=arabroot.io) تشرح ذلك بمعادلتين بسيطتين: مجموع الاحتمالات هو العدد المتوقع للثغرات التي سيرصد استغلالها خلال 30 يوماً، واحتمال أن تستغل واحدة على الأقل هو واحد ناقص حاصل ضرب (1 ناقص كل احتمال). وهاتان المعادلتان تفترضان أن الثغرات مستقلة عن بعضها، وهذا تقريب. والسكربت التالي يحسبهما لكل Container:

```python
"""Expected number of CVEs with exploitation activity in the next 30 days per asset (FIRST: sum of EPSS)."""
import csv, json, sys
epss = {}
with open("epss.csv") as f:
    next(f)
    epss = {r["cve"]: float(r["epss"]) for r in csv.DictReader(f)}
for name in sys.argv[1:]:
    cves = {v["VulnerabilityID"] for r in json.load(open(f"scans/{name}.json")).get("Results", [])
            for v in r.get("Vulnerabilities") or []}
    p = [epss.get(c, 0.0) for c in cves]
    none = 1.0
    for x in p:
        none *= 1 - x
    print(f"{name:14} CVEs={len(cves):5}  sum(EPSS)={sum(p):5.2f}  P(at least one)={1 - none:.3f}  "
          f"without the brotli CVE: {sum(epss.get(c, 0) for c in cves if c != 'CVE-2026-111497'):5.2f}")
```

```text
edge-nginx     CVEs=   39  sum(EPSS)= 0.66  P(at least one)=0.601  without the brotli CVE:  0.11
shop-api       CVEs= 2521  sum(EPSS)=12.07  P(at least one)=1.000  without the brotli CVE: 11.51
shop-api-slim  CVEs=  117  sum(EPSS)= 1.40  P(at least one)=0.864  without the brotli CVE:  1.40
shop-db        CVEs=   86  sum(EPSS)= 0.39  P(at least one)=0.324  without the brotli CVE:  0.39
```

وهنا يجب أن تقرأ الأرقام بحذر، فالرقم 12.07 في `shop-api` يبدو مخيفاً، ولكن أعلى ثغراته احتمالاً هي CVE-2004-0230 باحتمال 0.80، وهي ثغرة قديمة في بروتوكول TCP نفسه ظهرت في حزمة `linux-libc-dev`. وهذه الحزمة هي ملفات ترويسات النواة Kernel Headers التي يحتاجها المترجم Compiler عند بناء البرامج، ولا يوجد داخل ال Container أي نواة تعمل منها، لأن ال Container يستخدم نواة السيرفر. فالاحتمال صحيح للثغرة في العالم، وخاطئ لهذه الحزمة في هذا المكان، وهذا أهم حدود EPSS: أنه يقيس الثغرة لا الحزمة التي عندك، ولا يعرف شيئاً عن طريقة تشغيلك لها.

## قائمة KEV: الدليل على الاستغلال

قائمة الثغرات المستغلة المعروفة KEV (Known Exploited Vulnerabilities) أنشأتها وكالة الأمن السيبراني وأمن البنية التحتية الأمريكية CISA في نوفمبر 2021، وكانت في نسخة 27 أكتوبر 2026 التي استخدمناها تضم 1760 ثغرة. وتشرح [صفحة معايير القائمة](https://www.cisa.gov/known-exploited-vulnerabilities?ref=arabroot.io) ثلاثة شروط لدخول أي ثغرة: أن يكون لها رقم CVE، وأن يوجد دليل موثوق على استغلالها في هجمات حقيقية، وأن يوجد إجراء واضح لإصلاحها مثل تحديث من المورد. والشرط الثالث مهم أكثر مما يبدو، فالثغرة المستغلة التي لا إصلاح لها لا تدخل القائمة حتى يصدر إصلاح، لأن القائمة صممت لتكون قائمة عمل لا قائمة تحذير.

والقائمة ملف JSON واحد تستطيع تنزيله كل يوم، وهذا سجل ثغرة Brotli فيه كما نزلناه:

```json
{
 "cveID": "CVE-2026-111497",
 "vendorProject": "Google",
 "product": "Brotli",
 "vulnerabilityName": "Google Brotli Unchecked Return Value Vulnerability",
 "dateAdded": "2026-10-27",
 "dueDate": "2026-11-10",
 "knownRansomwareCampaignUse": "Unknown",
 "forensicTriage": "No",
 "cwes": ["CWE-252", "CWE-787"]
}
```

في السجل أعلاه، بعد اختصار الوصف والملاحظات، لاحظ التالي:

- **تاريخ الإضافة `dateAdded`:** هو اليوم الذي اقتنعت فيه CISA بالدليل، لا يوم بداية الاستغلال، وقد رأينا أن CISA نفسها قالت إن الاستغلال نشط قبل ذلك بأربعة أيام.
- **الموعد النهائي `dueDate`:** بعد 14 يوماً من الإضافة، وهو ملزم للجهات الفدرالية الأمريكية، وللشركات مرجع جيد لا أكثر.
- **استخدامها في الفدية `knownRansomwareCampaignUse`:** Known أو Unknown، وهي معلومة تستحق أن ترفع الأولوية عندما تكون Known.
- **الفحص الجنائي `forensicTriage`:** حقل يرتبط بالتوجيه BOD 26-04، ويقول هل تطلب CISA فحصاً للأنظمة المتأثرة للتأكد أنها لم تخترق قبل الإصلاح، وسوف نعود إليه.

### من BOD 22-01 إلى BOD 26-04

ارتبطت القائمة منذ إنشائها بالتوجيه الملزم BOD 22-01 الذي يلزم الجهات الفدرالية الأمريكية بإصلاح ما فيها بمواعيد محددة. وفي 10 يونيو 2026 أصدرت CISA التوجيه [BOD 26-04 لترتيب التحديثات الأمنية بحسب الخطر](https://www.cisa.gov/news-events/directives/bod-26-04-prioritizing-security-updates-based-risk?ref=arabroot.io)، وهو يلغي BOD 22-01 وBOD 19-02 ويحل محلهما. والفرق الجوهري أن التوجيه القديم كان يقول «أصلح ما في القائمة خلال أسبوعين»، والجديد يحسب المهلة من أربعة أسئلة: هل الثغرة في KEV، وهل النظام مكشوف للإنترنت، وهل يمكن أتمتة الاستغلال، وهل يعطي المهاجم سيطرة كاملة أم جزئية. وتقول [صفحة القائمة](https://www.cisa.gov/known-exploited-vulnerabilities?ref=arabroot.io) إن التوجيه الجديد حمل معه معايير KEV كما هي، وأضاف إليها هذه الأسئلة.

وتبقى للقائمة حدود يجب أن تعرفها قبل أن تجعلها أساس سياستك. فهي متأخرة بطبيعتها، لأنها تنتظر الدليل والإصلاح معاً، ونطاقها ما يهم الحكومة الأمريكية أولاً، فقد تجد ثغرة مستغلة في منتج منتشر في المنطقة ولا تجدها في القائمة. وغياب الثغرة من KEV لا يعني أنها آمنة، وإنما يعني أن CISA لم تقتنع بعد أو لم تهتم، وهذا ما يجعلها إشارة قوية عندما تقول «نعم»، وضعيفة عندما تسكت.

## من الرقم إلى القرار: SSVC وجدول BOD 26-04

الإشارات الثلاث أرقام، والفريق يحتاج قراراً: هل نصلح الليلة، أم هذا الأسبوع، أم في دورة التحديث العادية؟ والطريقة البسيطة أن تجمع الأرقام في معادلة، مثل CVSS ضرب EPSS، وهذه طريقة لا ينصح بها، والسبب أنك تضرب سؤالين مختلفين، فتخرج برقم لا يعرف أحد معناه ولا يستطيع أحد أن يدافع عنه أمام المدير أو المدقق. أما الطريقة التي تبنتها CISA فهي شجرة قرار، أي أسئلة قليلة لكل منها إجابات قليلة، وكل مسار في الشجرة ينتهي بقرار مكتوب.

### شجرة SSVC: أسئلة قليلة وقرار مكتوب

بنى معهد هندسة البرمجيات SEI في جامعة كارنيجي ميلون مع CISA نظام [التصنيف الخاص بأصحاب المصلحة SSVC](https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc?ref=arabroot.io) في 2019، ثم بنت CISA شجرتها الخاصة في 2020\. والشجرة تنتهي بأربعة قرارات: تابع Track أي أصلح في الموعد العادي، وتابع بانتباه Track\* أي في الموعد العادي مع مراقبة أي تغير، واهتم Attend أي أبلغ المشرفين وأصلح أسرع من الموعد العادي، وتحرك Act أي يجتمع المشرفون والقيادة ويصلح الفريق بأسرع ما يمكن. وتصل إلى القرار من خمسة أسئلة، كما في [دليل CISA لنظام SSVC](https://www.cisa.gov/sites/default/files/publications/cisa-ssvc-guide%20508c.pdf?ref=arabroot.io):

- **حالة الاستغلال Exploitation:** لا يوجد None، أو إثبات مفهوم منشور Public PoC، أو استغلال نشط Active بدليل موثوق.
- **قابلية الأتمتة Automatable:** هل يستطيع المهاجم أتمتة الخطوات الأربع الأولى، أي الاستطلاع والتجهيز والإيصال والاستغلال؟ ويكفي حاجز واحد فعال مثل اشتراط تسجيل الدخول لتكون الإجابة لا.
- **الأثر التقني Technical Impact:** جزئي Partial أو كامل Total، والكامل أن يسيطر المهاجم على البرنامج بالكامل أو يكشف كل بياناته، وحجب الخدمة يعد جزئياً.
- **انتشار المهمة Mission Prevalence والأثر على الناس Public Well-being:** يجمعهما الجدول في سؤال واحد عن أهمية النظام للمهمة الأساسية وأثر اختراقه على الناس، بثلاث إجابات منخفض ومتوسط وعال.

ولاحظ أن الشجرة لا تقبل إجابة «لا أعرف»، فالدليل يطلب أن تختار أكثر إجابة معقولة بحسب ما حدث سابقاً، وأن تكتب تاريخ الإجابة لأن حالة الاستغلال تتغير. والأهم من ذلك أن CISA لا تتركك تجيب وحدك عن الأسئلة الثلاثة الأولى، فبرنامج Vulnrichment ينشر إجاباتها لآلاف الثغرات داخل سجل CVE نفسه، في جزء اسمه CISA ADP، ولثغرة Brotli كانت الإجابات بتاريخ 23 أكتوبر: الاستغلال نشط، والأتمتة لا، والأثر كامل.

### جدول BOD 26-04: أربعة أسئلة وخمس مهل

بنت CISA جدول المهل في التوجيه الجديد على نفس الفكرة، مع تغيير واحد: بدل سؤال أهمية المهمة جاء سؤال «هل النظام مكشوف للإنترنت Publicly Exposed؟»، وبدل حالة الاستغلال جاء سؤال «هل الثغرة في KEV؟». والجدول منشور ملفاً مقروءاً للآلة في [مستودع SSVC](https://github.com/CERTCC/SSVC?ref=arabroot.io)، والصورة التالية تبين صفوفه الستة عشر مرتبة بالمهلة:

![جدول من ستة عشر صفاً بأعمدة: في قائمة KEV، ومكشوف للإنترنت، وقابل للأتمتة، والأثر التقني جزئي أو كامل، والمهلة: عند التحديث القادم للنظام لصفين بلا أي إجابة نعم، و60 يوماً لثلاثة صفوف، و14 يوماً لستة صفوف، و3 أيام لصفين، و3 أيام مع فحص جنائي Forensic Triage لثلاثة صفوف كلها في KEV وأثرها كامل](https://arabroot.io/content/images/2026/10/vuln-prioritization-05-bod2604.webp)

كل صف في KEV وأثره كامل ومعه سؤال آخر بنعم ينتهي بفحص جنائي قبل الإصلاح

والمهلة الأشد في الجدول «3 أيام مع فحص جنائي»، وتشرح [إرشادات تطبيق التوجيه](https://www.cisa.gov/news-events/directives/bod-26-04-implementation-guidance-prioritizing-security-updates-based-risk?ref=arabroot.io) سببها: إذا كانت الثغرة مستغلة فعلاً، وكان نظامك مكشوفاً لها، فاحتمال أن يكون قد اخترق قبل أن تعرف ليس صغيراً، والتحديث وحده يغلق الباب ولا يخرج من دخل. لذلك تطلب الإرشادات ست خطوات بمواعيد مقترحة من لحظة الإضافة إلى KEV: تحديد النطاق خلال ساعتين، وجمع الأدلة قبل أي تغيير خلال 2 إلى 24 ساعة، ثم التحديث، ثم العزل، ثم التحليل، ثم قرار التصعيد خلال 48 إلى 72 ساعة. ولاحظ الترتيب: الأدلة قبل التحديث، لأن التحديث وإعادة التشغيل قد يمحوان ما في الذاكرة، وهذا ما شرحناه في [التحقيق الرقمي للمبتدئين](https://arabroot.io/articles/%D8%A7%D9%84%D8%AA%D8%AD%D9%82%D9%8A%D9%82-%D8%A7%D9%84%D8%B1%D9%82%D9%85%D9%8A-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-dfir/).

والجدول ملزم للجهات الفدرالية الأمريكية فقط، ولا يلزم أي شركة في المملكة بشيء. ولكننا نستخدمه في هذا المقال لأنه أوضح مثال منشور لسياسة ترتيب كاملة: أسئلة قليلة، وإجابات تنشر ثلاثاً منها جهة عامة مجاناً، وسؤال واحد عنك أنت، ومهلة مكتوبة لكل احتمال.

## السياق الذي لا تعرفه أي قاعدة بيانات

كل ما سبق يأتي من مصادر عامة، وكلها تجيب عن سؤال «ما هذه الثغرة؟». أما سؤال «ماذا تعني هذه الثغرة عندي؟» فلا يجيب عنه أحد غيرك، وفيه أربعة أجزاء:

- **الانكشاف Exposure:** هل يصل إلى النظام أحد من خارج الشبكة؟ و`edge-nginx` مكشوف بالتعريف، و`shop-db` لا. وتعريف CISA للانكشاف واسع عن قصد: أي نظام يصل إليه شخص غير موثوق أو غير مسجل عبر شبكة عامة، أينما كان مكانه.
- **الأهمية Criticality:** ماذا يحدث إذا توقف النظام أو تسربت بياناته؟ قاعدة بيانات العملاء أهم من Container يولد تقارير داخلية.
- **الوصول إلى الكود المصاب Reachability:** هل يستخدم برنامجك الجزء المصاب فعلاً؟ ففي المختبر سألنا ال Image نفسها لماذا توجد مكتبة Brotli فيها، فكانت الإجابة أن `libcurl` و`freetype` يحتاجانها، وأن nginx نفسه لم يبن بوحدة Brotli. أي أن ال Proxy لا يفك بيانات Brotli يرسلها له العميل، وإنما قد تفعل ذلك أداة curl إذا استخدمها أحد داخل ال Container.
- **الحماية الموجودة Compensating Controls:** جدار حماية تطبيقات الويب WAF، أو تقسيم الشبكة Network Segmentation، أو أن الخدمة لا تعمل بصلاحيات root.

والسؤال الثالث هو أخطر الأسئلة، لأنه يغري بالكسل: «nginx لا يستخدم Brotli، إذن لا يهمنا الأمر». وهذا استنتاج صحيح غالباً ولكنه يحتاج تحققاً لا ظناً، والتحقق يكلف أكثر من الإصلاح نفسه في هذه الحالة، فإصلاح Brotli في ال Proxy هو إعادة بناء ال Image من إصدار أحدث، وهي عملية دقائق. لذلك فالقاعدة العملية: استخدم الوصول إلى الكود المصاب لتؤخر ما يصعب إصلاحه، لا لتؤجل ما يسهل.

وأهم جزء من السياق في عالم ال Containers هو وحدة العمل Unit of Work. فالفاحص يعطيك سطراً لكل ثغرة في كل حزمة، ولكنك لا تصلح ثغرة، وإنما تحدث حزمة أو تعيد بناء Image أو تغير ال Image الأساسية Base Image كلها. والصورة التالية تبين ما يعنيه ذلك بالأرقام في `shop-api`:

![أربع لوحات من اليمين: 4871 نتيجة فحص منها 1887 في حزمة ترويسات النواة linux-libc-dev وحدها، ثم 2521 ثغرة مختلفة لأن الثغرة الواحدة تظهر في أكثر من حزمة مثل libbrotli1 وlibbrotli-dev، ثم 211 حزمة منها 25 فقط لها إصدار مصلح الآن، ثم قرار واحد هو تغيير ال Image إلى bookworm-slim فيترك 246 نتيجة بدل 4871](https://arabroot.io/content/images/2026/10/vuln-prioritization-06-units.webp)

أكثر من ثلث النتائج من حزمة واحدة لا تعمل أصلاً داخل ال Container

والدرس من هذه الأرقام أن أول سؤال في الترتيب ليس «أي ثغرة؟»، وإنما «ما الذي يحذف أكثر النتائج بأقل تغيير؟». فال Image الكاملة `node:24.22.1-bookworm` تحمل أدوات البناء ومكتبات الصور وترويسات النواة، وهي مفيدة في مرحلة بناء التطبيق، ولا حاجة لها عند تشغيله، وهذا ما سوف نقيسه في التجربة الثانية.

## تجربة عملية: من 5025 نتيجة إلى قائمة عمل

الآن نبني كل ما سبق على جهازك. نفحص ال Images الثلاث بأداة Trivy، ثم نجمع ثلاثة مصادر عامة: قائمة KEV كاملة، وملف EPSS اليومي كاملاً، وإجابات CISA لكل CVE في التقرير، ثم نكتب سكربتاً يطبق أربع سياسات على نفس النتائج ويعد ما تضعه كل واحدة أمام الفريق. ولا يحتاج المختبر أي منفذ، فكل شيء يقرأ ملفات، ولا يحتاج إلا Docker وPython داخل Container.

### ملف الأصول أولاً

قبل الفحص نكتب ما نعرفه عن كل نظام، لأن هذا الملف هو السؤال الرابع، ولا يستطيع أي سكربت أن يخمنه:

```text
asset,image,publicly_exposed,mission,note
edge-nginx,nginx:1.31.6-alpine,yes,high,reverse proxy in front of the store; port 443 open to the internet
shop-api,node:24.22.1-bookworm,yes,high,store API behind the proxy; receives customer requests
shop-db,mariadb:11.4.13,no,high,customer and order database; internal network only
```

ولاحظ أننا كتبنا `shop-api` مكشوفاً مع أنه خلف ال Proxy، والسبب أن طلبات العملاء تصل إليه كما هي بعد أن يمررها nginx، فهو يستقبل بيانات من غير موثوقين، وهذا هو المعيار في تعريف CISA، لا وجود منفذ مفتوح مباشرة.

### الفحص بأداة Trivy

نستخدم [Trivy 0.76.1](https://github.com/aquasecurity/trivy/releases/tag/v0.76.1?ref=arabroot.io) الصادر في 21 أكتوبر 2026 برخصة Apache 2.0\. وأول ما يفعله تنزيل قاعدة بيانات الثغرات، فنضعها في Volume حتى لا تنزل مع كل فحص:

```bash
docker volume create trivy-cache
MSYS_NO_PATHCONV=1 docker run --rm -v trivy-cache:/root/.cache aquasec/trivy:0.76.1 image --download-db-only
```

```text
INFO	[vulndb] Downloading vulnerability DB...
INFO	[vulndb] Downloading artifact...	repo="mirror.gcr.io/aquasec/trivy-db:2"
130.06 MiB / 130.06 MiB [-----------------------------------------------] 100.00% 1.20 MiB p/s 1m49s
INFO	[vulndb] Artifact successfully downloaded	repo="mirror.gcr.io/aquasec/trivy-db:2"
```

والملف المضغوط 130 ميجابايت، ولكنه بعد فك الضغط شغل 1.5 جيجابايت داخل ال Volume، فاحسب ذلك إذا كان القرص صغيراً. ثم نفحص ال Images الثلاث ونحفظ النتائج بصيغة JSON، مع ثلاثة خيارات لها سبب:

```bash
mkdir -p scans
for pair in edge-nginx=nginx:1.31.6-alpine shop-api=node:24.22.1-bookworm shop-db=mariadb:11.4.13; do
  MSYS_NO_PATHCONV=1 docker run --rm -v trivy-cache:/root/.cache -v /var/run/docker.sock:/var/run/docker.sock \
    -v "$(pwd -W)/scans:/out" aquasec/trivy:0.76.1 image --quiet --timeout 30m --skip-db-update \
    --skip-java-db-update --scanners vuln --format json -o "/out/${pair%%=*}.json" "${pair#*=}"
done
```

- `--scanners vuln` لأننا نريد الثغرات فقط، لا كلمات المرور المنسية Secrets ولا الإعدادات.
- `--skip-java-db-update` لأن قاعدة بيانات مكتبات Java وحدها قرابة جيجابايت، ولا يوجد Java في ال Images الثلاث.
- `--timeout 30m` وهذا الخيار أضفناه بعد أول محاولة، فقد فشل فحص `node:24.22.1-bookworm` بالخطأ `context deadline exceeded`، لأن المهلة الافتراضية خمس دقائق، وال Image حجمها 1.65 جيجابايت، فاحتاج الفحص 7 دقائق و31 ثانية. فإذا ظهر لك هذا الخطأ مع Image كبيرة فالسبب المهلة لا الشبكة.

### المصادر الثلاثة: KEV وEPSS وإجابات CISA

قائمة KEV ملف واحد، وملف EPSS اليومي ملف واحد مضغوط، ولاحظ أن رابط EPSS يحول إلى ملف اليوم، فلا بد من الخيار `-L` مع curl كما تقول صفحة البيانات:

```bash
curl -s -o kev.json https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json
curl -sL https://epss.empiricalsecurity.com/epss_scores-current.csv.gz | gunzip > epss.csv
head -2 epss.csv
```

```text
#model_version:v2026.06.15,score_date:2026-10-27T12:03:15Z
cve,epss,percentile
```

والملف فيه 396,257 ثغرة بعد سطري الترويسة، وحجمه المضغوط 2.8 ميجابايت فقط، ولذلك ينصح موقع EPSS باستخدامه للعمل الجماعي بدل سؤال ال API عن كل ثغرة. أما إجابات CISA فلا يوجد لها ملف واحد، وإنما هي داخل سجل كل CVE، فنسألها من واجهة [خدمات CVE](https://cveawg.mitre.org/api/cve/CVE-2026-111497?ref=arabroot.io) لكل ثغرة في التقرير، ونحفظها في ملف حتى يعمل سكربت الترتيب بلا شبكة:

```python
"""Reads every CVE id in the Trivy reports and fetches CISA's Vulnrichment SSVC answers
   (Exploitation, Automatable, Technical Impact) from the CVE record (CVE Services API).
   Caches the answers in ssvc.json so the prioritisation script runs offline."""
import json, glob, urllib.request, concurrent.futures as cf

ids = sorted({v["VulnerabilityID"] for f in glob.glob("scans/*.json")
              for r in json.load(open(f)).get("Results", []) for v in r.get("Vulnerabilities") or []
              if v["VulnerabilityID"].startswith("CVE-")})

def ssvc(cve):
    try:
        with urllib.request.urlopen(f"https://cveawg.mitre.org/api/cve/{cve}", timeout=30) as r:
            rec = json.load(r)
    except Exception as e:
        return cve, {"error": str(e)[:60]}
    for adp in rec.get("containers", {}).get("adp", []):
        for m in adp.get("metrics", []):
            o = m.get("other", {})
            if o.get("type") == "ssvc":
                return cve, {k: v for d in o["content"]["options"] for k, v in d.items()}
    return cve, {}

with cf.ThreadPoolExecutor(8) as ex:
    out = dict(ex.map(ssvc, ids))
json.dump(out, open("ssvc.json", "w"), indent=0)
print(f"{len(ids)} CVE ids, with SSVC: {sum(1 for v in out.values() if 'Exploitation' in v)}, "
      f"no SSVC: {sum(1 for v in out.values() if v == {})}, errors: {sum(1 for v in out.values() if 'error' in v)}")
```

```bash
docker run --rm -v "$(pwd -W):/w" -w /w python:3.13.17-slim python fetch_ssvc.py
```

```text
2576 CVE ids, with SSVC: 1118, no SSVC: 1455, errors: 3
```

واستغرق السؤال عن 2576 ثغرة قرابة عشر دقائق بثمانية طلبات متوازية. والأرقام نفسها درس: أقل من نصف الثغرات لها إجابات من CISA، لأن برنامج Vulnrichment بدأ في 2024 ويغطي الثغرات الجديدة أولاً، وأغلب ثغرات تقريرنا قديمة من حزم Debian. والأخطاء الثلاثة كانت رد 404 لثغرات لها رقم محجوز Reserved لم ينشر سجله بعد، وتعرفها التوزيعة من مصادرها. وفي التقرير أيضاً 31 معرفاً ليست CVE أصلاً، 30 منها بصيغة `TEMP-` وهي معرفات مؤقتة يعطيها فريق Debian الأمني لمشكلة لم يصدر لها رقم CVE بعد، وواحد بصيغة `DLA` وهو رقم نشرة دعم طويل المدى. وهذه كلها لا يعرفها EPSS ولا KEV، فهي تبقى في السياسة بلا إشارات.

### سكربت الترتيب prioritize.py

السكربت يقرأ التقارير الثلاثة، ويربط كل نتيجة بالمصادر الثلاثة وبملف الأصول، ثم يطبق جدول BOD 26-04 كما نشرته CISA في [ملف CSV في مستودع SSVC](https://github.com/CERTCC/SSVC/blob/main/data/csv/cisa/cisa%5Fbod%5F26%5F04%5F1%5F0%5F0.csv?ref=arabroot.io)، ويقارن السياسات:

```python
"""Turns Trivy reports into a work list: joins each finding with CISA KEV, FIRST EPSS and CISA
   Vulnrichment SSVC answers, then compares policies by how many items they put in front of the team.
   usage: python prioritize.py [unknown=worst|best] [api-report-name]"""
import csv, json, sys, collections

UNKNOWN = sys.argv[1] if len(sys.argv) > 1 else "worst"     # how to treat a CVE without SSVC answers
API = sys.argv[2] if len(sys.argv) > 2 else "shop-api"
assets = {r["asset"]: r for r in csv.DictReader(open("assets.csv"))}
kev = {v["cveID"]: v for v in json.load(open("kev.json"))["vulnerabilities"]}
epss = {}
with open("epss.csv") as f:
    print(next(f).strip())                            # "#model_version:...,score_date:..."
    for r in csv.DictReader(f):
        epss[r["cve"]] = float(r["epss"])
ssvc = json.load(open("ssvc.json"))
# CISA BOD 26-04 decision table (CERTCC/SSVC data/csv/cisa/cisa_bod_26_04_1_0_0.csv)
table = {}
for r in csv.DictReader(open("bod2604.csv")):
    v = list(r.values())
    table[tuple(v[1:5])] = v[5]

def timeline(r):
    s = ssvc.get(r["cve"], {})
    au, ti = s.get("Automatable"), s.get("Technical Impact")
    if au is None or ti is None:                      # no Vulnrichment answers for this CVE
        au, ti = ("yes", "total") if UNKNOWN == "worst" else ("no", "partial")
    return table[("yes" if r["kev"] else "no", assets[r["asset"]]["publicly_exposed"], au, ti)]

rows = []
for a in assets:
    report = API if a == "shop-api" else a
    for res in json.load(open(f"scans/{report}.json")).get("Results", []):
        for v in res.get("Vulnerabilities") or []:
            c = v["VulnerabilityID"]
            rows.append(dict(asset=a, cve=c, pkg=v["PkgName"], fixed=v.get("FixedVersion", ""),
                             status=v.get("Status", ""), sev=v["Severity"], kev=c in kev, epss=epss.get(c, 0.0)))
for r in rows:
    r["bod"] = timeline(r)

print(f"report for shop-api: {API}; unknown SSVC treated as: {UNKNOWN}")
print(f"findings: {len(rows)}, unique CVEs: {len({r['cve'] for r in rows})}")
for a in assets:
    rs = [r for r in rows if r["asset"] == a]
    c = collections.Counter(r["sev"] for r in rs)
    st = collections.Counter(r["status"] for r in rs)
    print(f"  {a:10} {len(rs):5}  C={c['CRITICAL']} H={c['HIGH']} M={c['MEDIUM']} L={c['LOW']} U={c['UNKNOWN']}  "
          + " ".join(f"{k}={n}" for k, n in st.most_common()))

pol = {"severity CRITICAL+HIGH": [r for r in rows if r["sev"] in ("CRITICAL", "HIGH")],
       "in CISA KEV": [r for r in rows if r["kev"]],
       "EPSS >= 0.10": [r for r in rows if r["epss"] >= 0.10],
       "BOD 26-04: 3 days (+F)": [r for r in rows if r["bod"].startswith("3 days")],
       "BOD 26-04: 14 days": [r for r in rows if r["bod"] == "14 days"]}
print(f"\n{'policy':26} findings  CVEs  packages  with-fix")
for name, rs in pol.items():
    print(f"  {name:24} {len(rs):7} {len({r['cve'] for r in rs}):5} {len({(r['asset'], r['pkg']) for r in rs}):8}"
          f" {sum(1 for r in rs if r['fixed']):8}")
print("\nBOD 26-04 buckets:", dict(collections.Counter(r["bod"] for r in rows).most_common()))
print("\nKEV matches:")
for r in pol["in CISA KEV"]:
    k = kev[r["cve"]]
    print(f"  {r['cve']} {r['asset']:10} {r['pkg']:14} {r['sev']:5} epss={r['epss']:.3f} added={k['dateAdded']} "
          f"due={k['dueDate']} fixed={r['fixed'] or '-'} -> {r['bod']}")
```

في الكود أعلاه لاحظ التالي:

- الجدول لا نكتبه بأيدينا، وإنما نقرؤه من ملف CSV نزلناه من المستودع، والسبب أن أي خطأ في نقل ستة عشر صفاً سيغير قرارات حقيقية دون أن ينتبه أحد.
- الثغرة التي لا إجابات لها تعامل بحسب المعامل الأول: `worst` تفترض أنها قابلة للأتمتة وأثرها كامل، و`best` تفترض العكس. وهذا ليس تفصيلاً تقنياً، وإنما قرار سياسة، وسوف نرى أثره في التجربة الأولى.
- عمود `packages` في المقارنة يعد أزواج (Container، حزمة)، لأن هذا هو العمل الحقيقي: تحديث حزمة واحدة يغلق كل ثغراتها في ذلك ال Container.
- عمود `with-fix` يعد النتائج التي لها إصدار مصلح الآن، والفرق بينه وبين عدد النتائج هو ما لا تستطيع إصلاحه اليوم مهما كانت أولويته.

### النتيجة: أربع سياسات على نفس التقرير

```bash
docker run --rm -v "$(pwd -W):/w" -w /w python:3.13.17-slim python prioritize.py worst
```

والمخرج سوف يكون كما يلي:

```text
#model_version:v2026.06.15,score_date:2026-10-27T12:03:15Z
report for shop-api: shop-api; unknown SSVC treated as: worst
findings: 5025, unique CVEs: 2607
  edge-nginx    64  C=0 H=8 M=10 L=44 U=2  fixed=64
  shop-api    4871  C=35 H=603 M=2202 L=1952 U=79  affected=3988 fixed=436 fix_deferred=365 will_not_fix=82
  shop-db       90  C=1 H=25 M=53 L=10 U=1  fixed=62 affected=28

policy                     findings  CVEs  packages  with-fix
  severity CRITICAL+HIGH       672   330      102      192
  in CISA KEV                    3     1        3        3
  EPSS >= 0.10                  12     8        9        3
  BOD 26-04: 3 days (+F)      1963  1540      110       53
  BOD 26-04: 14 days           832   382      124      111

BOD 26-04 buckets: {'60 days': 2181, '3 days': 1960, '14 days': 832, 'fix on system upgrade': 49, '3 days & forensic investigation': 3}

KEV matches:
  CVE-2026-111497 edge-nginx brotli-libs    HIGH  epss=0.555 added=2026-10-27 due=2026-11-10 fixed=1.2.1-r0 -> 3 days & forensic investigation
  CVE-2026-111497 shop-api   libbrotli-dev  HIGH  epss=0.555 added=2026-10-27 due=2026-11-10 fixed=1.0.9-2+deb12u1 -> 3 days & forensic investigation
  CVE-2026-111497 shop-api   libbrotli1     HIGH  epss=0.555 added=2026-10-27 due=2026-11-10 fixed=1.0.9-2+deb12u1 -> 3 days & forensic investigation
```

في المخرج أعلاه لاحظ التالي:

- **توزيع النتائج:** 4871 من 5025 نتيجة في `shop-api` وحده، أي 97% من العمل في Container واحد، ومنها 436 فقط لها إصلاح. أما nginx على Alpine فكل نتائجه الأربع والستين لها إصلاح، لأن Alpine توزيعة صغيرة تتحدث بسرعة.
- **سياسة الخطورة:** 672 نتيجة في 102 حزمة، ومنها 192 فقط لها إصلاح، أي أن الفريق سيقضي أغلب وقته في تتبع ثغرات لا يستطيع إصلاحها، ويكتب لكل واحدة استثناءً.
- **سياسة KEV:** ثلاث نتائج لثغرة واحدة، Brotli في Containers اثنتين، وكلها لها إصلاح، وكلها تنتهي في الجدول إلى «3 أيام مع فحص جنائي»، لأنها في KEV والأثر كامل والنظامان مكشوفان.
- **سياسة EPSS:** 12 نتيجة في 8 ثغرات، و3 منها فقط لها إصلاح، وأغلبها في `linux-libc-dev` التي شرحنا لماذا لا يعني احتمالها شيئاً هنا.
- **جدول BOD 26-04:** 1963 نتيجة في مهلة 3 أيام، وهو رقم أكبر من سياسة الخطورة بثلاث مرات، والسبب ليس في الجدول، وإنما في قرارنا أن نعامل الثغرة المجهولة كأسوأ حال.

وقبل أن نتابع، ارجع إلى ثغرة Brotli في القائمة: الموعد في KEV هو 10 نوفمبر، أي 14 يوماً، بينما جدول BOD 26-04 يعطيها 3 أيام مع فحص جنائي، والحقل `forensicTriage` في سجلها يقول No. وليس في ذلك تناقض، فالموعد في القائمة واحد للجميع، والجدول يحسب المهلة لكل نظام بحسب انكشافه، وحقل الفحص الجنائي في القائمة إضافة تطلبها CISA لثغرات بعينها فوق ما يقوله الجدول. والقرار العملي للمتجر بسيط: الإصلاح خلال 3 أيام، لأن تحديث المكتبة إعادة بناء Image، ومعه نظرة سريعة في سجلات ال Proxy عن أي طلب غريب في الأسبوع الماضي، كما سنكتب في السياسة.

![أعمدة أفقية لعدد البنود من 5025 نتيجة: إصلاح كل شيء 5025 نتيجة في 2607 ثغرة، وجدول BOD 26-04 خلال 3 أيام مع معاملة المجهول كأسوأ حال 1963 نتيجة في 110 حزم، والخطورة حرجة أو عالية 672 نتيجة في 102 حزمة، وجدول BOD 26-04 مع معاملة المجهول كأفضل حال 96 نتيجة في 38 حزمة، واحتمال EPSS من 0.10 فأعلى 12 نتيجة في 9 حزم، وقائمة KEV 3 نتائج لثغرة واحدة في 3 حزم](https://arabroot.io/content/images/2026/10/vuln-prioritization-04-policies.webp)

نفس التقرير، وست سياسات، والفرق بين أكبرها وأصغرها 1675 ضعفاً

### ماذا يحدث إذا عاملت المجهول كأفضل حال؟

نعيد السكربت نفسه مع المعامل `best`، أي أن كل ثغرة لم تجب عنها CISA تعامل كأنها لا تقبل الأتمتة وأثرها جزئي:

```bash
docker run --rm -v "$(pwd -W):/w" -w /w python:3.13.17-slim python prioritize.py best
```

```text
policy                     findings  CVEs  packages  with-fix
  severity CRITICAL+HIGH       672   330      102      192
  in CISA KEV                    3     1        3        3
  EPSS >= 0.10                  12     8        9        3
  BOD 26-04: 3 days (+F)        96    52       38        3
  BOD 26-04: 14 days           832   382      124      111

BOD 26-04 buckets: {'60 days': 4047, '14 days': 832, '3 days': 93, 'fix on system upgrade': 50, '3 days & forensic investigation': 3}
```

نزلت مهلة 3 أيام من 1963 نتيجة إلى 96، ولم يتغير أي سطر آخر في السياسات الأخرى، وتغيرت فقط القرارات التي تعتمد على الإجابات المفقودة. وهنا السؤال الذي يجب أن يقرره الفريق كتابة لا السكربت: هل غياب المعلومة يعني الخطر أم الأمان؟ و[دليل SSVC](https://www.cisa.gov/sites/default/files/publications/cisa-ssvc-guide%20508c.pdf?ref=arabroot.io) لا يقبل «لا أعرف» كما ذكرنا، ويطلب أكثر إجابة معقولة بحسب ما حدث سابقاً. والإجابة المعقولة لثغرة عمرها عشر سنوات في حزمة ترويسات النواة، لم يرصد لها أي استغلال، ليست «أسوأ حال»، وإجابة ثغرة عمرها يومان في مكتبة تفك بيانات من الشبكة ليست «أفضل حال». لذلك فالحل الأنسب أن تعامل المجهول بحسب عمره: الثغرة الأحدث من 30 يوماً بلا إجابات تعامل كأسوأ حال حتى تصل الإجابات، والأقدم تعامل بحسب EPSS، فإن كان احتمالها أقل من 1% فهي على الأغلب لا تقبل الأتمتة عملياً.

### ماذا يحدث إذا غيرت ال Image بدل أن ترتب نتائجها؟

التجربة الثانية لا تغير السياسة، وإنما تغير ال Image. فبدل `node:24.22.1-bookworm` نستخدم `node:24.22.1-bookworm-slim` بنفس إصدار Node.js، وهي ال Image التي لا تحمل أدوات البناء ولا ترويسات النواة ولا مكتبات الصور، وحجمها 333 ميجابايت بدل 1.65 جيجابايت. نفحصها بنفس الأمر ونحفظ تقريرها باسم `shop-api-slim.json`، ثم نعيد السكربت ونطلب منه استخدامه:

```bash
docker run --rm -v "$(pwd -W):/w" -w /w python:3.13.17-slim python prioritize.py worst shop-api-slim
```

```text
report for shop-api: shop-api-slim; unknown SSVC treated as: worst
findings: 400, unique CVEs: 225
  edge-nginx    64  C=0 H=8 M=10 L=44 U=2  fixed=64
  shop-api     246  C=1 H=63 M=97 L=84 U=1  affected=171 fix_deferred=41 will_not_fix=17 fixed=17
  shop-db       90  C=1 H=25 M=53 L=10 U=1  fixed=62 affected=28

policy                     findings  CVEs  packages  with-fix
  severity CRITICAL+HIGH        98    52       28       40
  in CISA KEV                    1     1        1        1
  EPSS >= 0.10                   2     2        2        1
  BOD 26-04: 3 days (+F)        83    45       22       50
  BOD 26-04: 14 days            72    36       28       17

BOD 26-04 buckets: {'60 days': 196, '3 days': 82, '14 days': 72, 'fix on system upgrade': 49, '3 days & forensic investigation': 1}

KEV matches:
  CVE-2026-111497 edge-nginx brotli-libs    HIGH  epss=0.555 added=2026-10-27 due=2026-11-10 fixed=1.2.1-r0 -> 3 days & forensic investigation
```

في المخرج أعلاه لاحظ التالي:

- نتائج `shop-api` نزلت من 4871 إلى 246، أي 95% أقل، دون ترقية حزمة واحدة ودون أن نغير سطراً في التطبيق.
- ثغرة Brotli اختفت من `shop-api` تماماً، لأن ال Image الصغيرة لا تحمل المكتبة أصلاً، فبقيت نتيجة KEV واحدة في nginx.
- حتى مع معاملة المجهول كأسوأ حال نزلت مهلة 3 أيام من 1963 نتيجة إلى 83، والسبب أن أغلب الثغرات المجهولة كانت في حزم لا يحتاجها التطبيق.
- ال Image الصغيرة لها شرط: إذا كان التطبيق يحتاج أدوات بناء لتثبيت مكتباته، مثل مكتبة تبنى من كود C، فاستخدم البناء متعدد المراحل Multi-stage Build: المرحلة الأولى بال Image الكاملة للبناء، والثانية بالصغيرة للتشغيل.

وهذه التجربة أهم من كل جداول الترتيب في المقال، لأنها تقول إن أفضل ترتيب هو الذي لا تحتاج إليه. فكل حزمة لا تحتاجها في الإنتاج هي ثغرات مستقبلية ستظهر في تقريرك، وستحتاج من يقرؤها ويقرر فيها، وحذفها مرة واحدة يوفر هذا العمل كل أسبوع.

### حذف المختبر Cleanup

```bash
docker volume rm trivy-cache
docker image rm aquasec/trivy:0.76.1 node:24.22.1-bookworm-slim
rm -rf scans kev.json epss.csv ssvc.json
```

## سياسة مكتوبة لشركة صغيرة

كل ما سبق لا قيمة له إذا بقي في رأس شخص واحد، فالسياسة المكتوبة هي التي تجعل قرار الإصلاح يتخذ بنفس الطريقة يوم الأحد ويوم الخميس، ومع موظف جديد أو قديم. وهي أيضاً ما تطلبه الضوابط الأساسية للأمن السيبراني من الهيئة الوطنية للأمن السيبراني، فالضابط 2-10-3 في [وثيقة ECC-2:2024](https://cdn.nca.gov.sa/api/files/public/upload/86e09090-44e4-481f-bc28-355673607654%5FECC--2024-EN.pdf?ref=arabroot.io) يطلب أن تشمل متطلبات إدارة الثغرات تصنيف الثغرات بحسب خطورتها (2-10-3-2)، ومعالجتها بحسب تصنيفها والمخاطر المرتبطة بها (2-10-3-3)، والاشتراك في مصادر موثوقة للثغرات الجديدة (2-10-3-5). ولاحظ أن الضابط يقول «بحسب تصنيفها والمخاطر المرتبطة بها»، أي أن الخطورة وحدها لا تكفي حتى بنص الضابط. وقد شرحنا الضوابط وأيها ينطبق عليك في [الضوابط الأساسية بلغة بسيطة](https://arabroot.io/articles/%D8%A7%D9%84%D8%B6%D9%88%D8%A7%D8%A8%D8%B7-%D8%A7%D9%84%D8%A7%D8%B3%D8%A7%D8%B3%D9%8A%D8%A9-%D9%84%D9%84%D8%A7%D9%85%D9%86-%D8%A7%D9%84%D8%B3%D9%8A%D8%A8%D8%B1%D8%A7%D9%86%D9%8A-nca-ecc-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9/).

والجدول التالي مثال لسياسة متجر صغير مبنية على ما تعلمناه، والمهل فيه اقتراح يناسب فريقاً من شخصين، فعدلها بحسب فريقك، والمهم أن تكون مكتوبة ومعتمدة:

| المستوى | الشرط                                                                                                | المهلة                           | ماذا يحدث معه                                                   |
| ------- | ---------------------------------------------------------------------------------------------------- | -------------------------------- | --------------------------------------------------------------- |
| طارئ    | في KEV على نظام مكشوف، أو استغلال نشط بحسب CISA مع أثر كامل                                          | 3 أيام                           | نظرة في السجلات قبل التحديث، وإبلاغ المدير، ومراجعة بعد الإصلاح |
| عاجل    | في KEV على نظام داخلي، أو EPSS من 0.10 فأعلى على نظام مكشوف، أو ثغرة جديدة بلا إجابات على نظام مكشوف | 14 يوماً                         | تذكرة باسم مسؤول، ومتابعة أسبوعية لتغير الإشارات                |
| عادي    | عالية أو حرجة لها إصلاح، دون أي من الشروط السابقة                                                    | 60 يوماً أو دورة التحديث الشهرية | تجمع في تحديث واحد لكل Image                                    |
| متابعة  | بلا إصلاح، أو في حزمة لا تعمل وقت التشغيل                                                            | عند إعادة البناء القادمة         | مراجعة ربع سنوية، وحذف الحزم غير المطلوبة                       |

والسياسة لا تكتمل دون قسم الاستثناءات Exceptions، لأن بعض الثغرات لن تصلح في المهلة لأسباب حقيقية، مثل تطبيق قديم لا يعمل مع الإصدار الجديد. والاستثناء الصحيح له مالك، وسبب مكتوب، وحماية مؤقتة، وتاريخ انتهاء، ومكانه سجل المخاطر Risk Register لا البريد الإلكتروني، كما شرحنا في [مقال سجل المخاطر](https://arabroot.io/articles/%D8%B3%D8%AC%D9%84-%D8%A7%D9%84%D9%85%D8%AE%D8%A7%D8%B7%D8%B1-risk-register-%D9%85%D8%B9-simplerisk/). ونتائج الفحص نفسها تحتاج مكاناً تتابع فيه حالة كل بند ومن يعمل عليه، مثل DefectDojo.

[![](https://arabroot.io/content/images/2026/10/risk-register-cover-cover.webp)دليلسجل المخاطر Risk Register مع SimpleRisk على سيرفركنبني سجل مخاطر حقيقياً بنموذج الهيئة ثم بأداة SimpleRisk، ونرى لماذا أعطت الأداة كل المخاطر مستوى واحداً، وكيف تكتب منهجية تعطي الأرقام معناها.](https://arabroot.io/articles/%D8%B3%D8%AC%D9%84-%D8%A7%D9%84%D9%85%D8%AE%D8%A7%D8%B7%D8%B1-risk-register-%D9%85%D8%B9-simplerisk/)[![](https://arabroot.io/content/images/2026/10/defectdojo-lab-cover-cover.webp)دليلإدارة نتائج الفحص والثغرات مع DefectDojoاستوردنا نتائج Nuclei وOpenVAS الحقيقية إلى DefectDojo، فجمع التكرار وأغلق المصلح وحده، وكاد إعداد افتراضي واحد أن يفسد كل شيء.](https://arabroot.io/articles/%D8%A7%D8%AF%D8%A7%D8%B1%D8%A9-%D9%86%D8%AA%D8%A7%D8%A6%D8%AC-%D8%A7%D9%84%D9%81%D8%AD%D8%B5-%D9%88%D8%A7%D9%84%D8%AB%D8%BA%D8%B1%D8%A7%D8%AA-%D9%85%D8%B9-defectdojo/)[![](https://arabroot.io/content/images/2026/10/nca-ecc-cover-cover.webp)دليلالضوابط الأساسية للأمن السيبراني NCA ECC بلغة بسيطةكيف تقرأ الضوابط الأساسية ECC دون أن تضيع في أرقامها، وعلى من تنطبق، وما المطلوب من جهتك فعلاً في كل مكون.](https://arabroot.io/articles/%D8%A7%D9%84%D8%B6%D9%88%D8%A7%D8%A8%D8%B7-%D8%A7%D9%84%D8%A7%D8%B3%D8%A7%D8%B3%D9%8A%D8%A9-%D9%84%D9%84%D8%A7%D9%85%D9%86-%D8%A7%D9%84%D8%B3%D9%8A%D8%A8%D8%B1%D8%A7%D9%86%D9%8A-nca-ecc-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9/)

⚠️

لا تقم بتغيير المهلة بعد أن تظهر النتائج، والسبب أن السياسة التي تتغير لتناسب التقرير لا تحمي أحداً. فإذا وجدت أن المهلة غير واقعية فعدلها في المراجعة الدورية للسياسة، ووثق السبب، وطبقها على التقرير القادم.

## أخطاء شائعة

- **الترتيب بعمود الخطورة وحده:** رأينا أن الثغرة المستغلة الوحيدة كانت HIGH بين 633 نتيجة أخرى بنفس الكلمة، وأن 11 من 14 ثغرة حرجة كان احتمال استغلالها أقل من 1%.
- **اعتبار CVSS خطراً Risk:** الرقم الأساسي يفترض أن الثغرة تستغل الآن وأن نظامك في أسوأ إعداد، فهو سقف لا تقدير.
- **الخلط بين احتمال EPSS ومئينه:** 0.10 احتمال صغير الشكل ولكنه عند المئين 95، والمئين 90 حد واسع جداً.
- **قراءة EPSS لثغرة عمرها يوم:** رأينا ثغرة Brotli بـ 0.0048 في يومها الأول، ثم 0.555 بعد أربعة أيام.
- **انتظار KEV قبل التحرك:** القائمة تحتاج دليلاً وإصلاحاً معاً، فتأتي متأخرة بأيام، وغياب الثغرة منها لا يعني أنها آمنة.
- **جمع الإشارات في معادلة واحدة:** CVSS ضرب EPSS رقم لا معنى له ولا يستطيع أحد الدفاع عنه، أما شجرة القرار فكل قرار فيها له سبب مكتوب.
- **إخفاء قرار «المجهول» داخل السكربت:** رأينا أنه وحده غير مهلة 3 أيام من 96 نتيجة إلى 1963، فاكتبه في السياسة.
- **عد الثغرات بدل الحزم:** العمل الحقيقي تحديث حزمة أو إعادة بناء Image، وتقرير «5025 ثغرة» يخيف المدير ولا يخبر الفريق بما يفعله.
- **ترتيب النتائج قبل تنظيف ال Image:** تغيير ال Image إلى النسخة الصغيرة حذف 95% من النتائج في دقائق.
- **الإصلاح قبل الأدلة في الثغرات المستغلة:** إذا كان النظام مكشوفاً لثغرة مستغلة فاحفظ السجلات قبل التحديث وإعادة التشغيل، فقد يكون التحديث متأخراً.

## قائمة تحقق قبل أن تقرر

| السؤال                                 | من أين الإجابة؟                          | إذا كانت الإجابة نعم                                           |
| -------------------------------------- | ---------------------------------------- | -------------------------------------------------------------- |
| هل الثغرة في KEV؟                      | ملف KEV اليومي، وحقل forensicTriage      | أعلى أولوية على الأنظمة المكشوفة، وانظر في السجلات قبل التحديث |
| هل قالت CISA إن الاستغلال نشط Active؟  | جزء CISA ADP في سجل CVE                  | عاملها كأنها في KEV ولو لم تدخلها بعد                          |
| هل النظام مكشوف لغير الموثوقين؟        | ملف الأصول                               | اختصر المهلة درجة                                              |
| هل الثغرة أحدث من 30 يوماً بلا إجابات؟ | تاريخ نشر CVE وVulnrichment              | عاملها كأسوأ حال حتى تصل الإجابات، وراجع EPSS يومياً           |
| هل احتمال EPSS من 0.10 فأعلى؟          | ملف EPSS اليومي                          | تحقق أن الحزمة تعمل فعلاً وقت التشغيل قبل أن ترفع أولويتها     |
| هل يوجد إصلاح الآن؟                    | حقل FixedVersion وحالة الثغرة في التقرير | إن لم يوجد: حماية مؤقتة واستثناء في سجل المخاطر                |
| هل تحتاج الحزمة في الإنتاج أصلاً؟      | ملف بناء ال Image                        | إن لم تحتجها: احذفها أو غير ال Image، فهذا أرخص من أي ترتيب    |
| ما وحدة العمل؟                         | عمود الحزمة في التقرير                   | اجمع الثغرات في تحديث حزمة أو إعادة بناء Image واحدة           |

## الخلاصة

- الاستغلال نادر: نحو 0.5% من الثغرات في KEV، ونحو 3% يرصد لها نشاط في أي شهر، فالترتيب هو البحث عن القلة لا إصلاح الكثرة.
- CVSS يقول ما أسوأ ما يحدث، ويفترض الاستغلال ما لم تقل غير ذلك، وأسئلة البيئة تحركه درجة أو اثنتين لا أكثر.
- EPSS احتمال حقيقي يتغير كل يوم ويمكن جمعه، ولكنه يقيس الثغرة في العالم لا الحزمة عندك، ويتأخر في الأيام الأولى.
- KEV أقوى إشارة عندما تقول نعم، وأضعفها عندما تسكت، وقد حل التوجيه BOD 26-04 محل BOD 22-01 بجدول من أربعة أسئلة.
- في المختبر وضعت الخطورة 672 نتيجة أمام الفريق، وKEV ثلاثاً، وجدول BOD 26-04 بين 96 و1963 بحسب قرار واحد عن المجهول.
- أكبر تخفيض لم يأت من أي سياسة، وإنما من تغيير ال Image إلى النسخة الصغيرة: من 4871 نتيجة إلى 246.
- اكتب السياسة بمهلها واستثناءاتها وقرارها عن المجهول، فهذا ما يطلبه الضابط 2-10-3 في ECC، وما يجعل القرار واحداً كل أسبوع.

وأقرب المقالات إلى هذا الموضوع في المسار:

[![](https://arabroot.io/content/images/2026/10/vuln-management-cover-cover.webp)دليلإدارة الثغرات Vulnerability Management: هل سيرفرك متأثر؟كيف تعرف خلال ساعات أن ثغرة جديدة تمس سيرفراتك، ولماذا يخدعك رقم الإصدار، وكيف ترتب الإصلاح وتتأكد أنه تم فعلاً.](https://arabroot.io/articles/%D8%A7%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%AB%D8%BA%D8%B1%D8%A7%D8%AA-vulnerability-management-%D9%84%D8%B3%D9%8A%D8%B1%D9%81%D8%B1%D8%A7%D8%AA%D9%83/)[![](https://arabroot.io/content/images/2026/10/vuln-tools-cover-cover.webp)دليلأدوات إدارة الثغرات Vulnerability Management مفتوحة المصدرأي أداة مفتوحة المصدر تجرد سيرفراتك وتطابقها مع الثغرات وتنبهك بالجديد، وماذا رأى Trivy وGrype فعلاً في ثغرات أكتوبر.](https://arabroot.io/articles/%D8%A7%D8%AF%D9%88%D8%A7%D8%AA-%D8%A7%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%AB%D8%BA%D8%B1%D8%A7%D8%AA-%D9%85%D9%81%D8%AA%D9%88%D8%AD%D8%A9-%D8%A7%D9%84%D9%85%D8%B5%D8%AF%D8%B1/)[![](https://arabroot.io/content/images/2026/10/vuln-lab-cover-cover.webp)دليلمختبر Lab: اكتشف السيرفرات المتأثرة بثغرة CVE جديدة وأصلحهافحصنا ثلاثة سيرفرات قديمة وسيرفراً محدثاً بأدوات Trivy وWazuh وسكربت تنبيه صغير، فظهر من يكتشف ثغرة الأسبوع ومن يفوته.](https://arabroot.io/articles/%D9%85%D8%AE%D8%AA%D8%A8%D8%B1-%D8%A7%D9%83%D8%AA%D8%B4%D8%A7%D9%81-%D8%A7%D9%84%D8%B3%D9%8A%D8%B1%D9%81%D8%B1%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%AA%D8%A7%D8%AB%D8%B1%D8%A9-%D8%A8%D8%AB%D8%BA%D8%B1%D8%A9-cve-%D9%88%D8%A7%D8%B5%D9%84%D8%A7%D8%AD%D9%87%D8%A7/)[![](https://arabroot.io/content/images/2026/10/openvas-lab-cover-cover.webp)دليلالفحص الشبكي للثغرات Network Scan مع OpenVASشغلنا منصة Greenbone المجتمعية وفحصنا بها سيرفر Debian، فانتظرنا أربع ساعات قبل أول فحص ووجدنا نتائج حرجة كلها إنذارات خاطئة.](https://arabroot.io/articles/%D9%81%D8%AD%D8%B5-%D8%A7%D9%84%D8%AB%D8%BA%D8%B1%D8%A7%D8%AA-%D8%A7%D9%84%D8%B4%D8%A8%D9%83%D9%8A-%D9%85%D8%B9-openvas-greenbone-%D9%81%D9%8A-%D9%85%D8%AE%D8%AA%D8%A8%D8%B1/)[![](https://arabroot.io/content/images/2026/10/nuclei-lab-cover-cover.webp)دليلفحص الثغرات المعروفة Known Vulnerabilities مع Nucleiشغلنا Nuclei على خدمات قديمة في شبكة Docker معزولة، فأصاب في ثغرات Apache وGrafana وأعطى أربعة إنذارات خاطئة على Redis.](https://arabroot.io/articles/%D9%81%D8%AD%D8%B5-%D8%A7%D9%84%D8%AB%D8%BA%D8%B1%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B9%D8%B1%D9%88%D9%81%D8%A9-%D9%85%D8%B9-nuclei-%D9%81%D9%8A-%D9%85%D8%AE%D8%AA%D8%A8%D8%B1-%D9%85%D8%B9%D8%B2%D9%88%D9%84/)[![](https://arabroot.io/content/images/2026/10/defectdojo-lab-cover-cover.webp)دليلإدارة نتائج الفحص والثغرات مع DefectDojoاستوردنا نتائج Nuclei وOpenVAS الحقيقية إلى DefectDojo، فجمع التكرار وأغلق المصلح وحده، وكاد إعداد افتراضي واحد أن يفسد كل شيء.](https://arabroot.io/articles/%D8%A7%D8%AF%D8%A7%D8%B1%D8%A9-%D9%86%D8%AA%D8%A7%D8%A6%D8%AC-%D8%A7%D9%84%D9%81%D8%AD%D8%B5-%D9%88%D8%A7%D9%84%D8%AB%D8%BA%D8%B1%D8%A7%D8%AA-%D9%85%D8%B9-defectdojo/)

## سجل التحديثات

- أكتوبر 2026: كتابة المقال، وفحص ثلاث Images يوم 28 أكتوبر 2026 بأداة Trivy 0.76.1، مع قائمة KEV بنسخة 2026.10.27 (1760 ثغرة)، وبيانات EPSS بالنموذج v2026.06.15 ليوم 27 أكتوبر، وإجابات CISA Vulnrichment من خدمات CVE، وجدول BOD 26-04 من مستودع SSVC.