الدقة
ثلاثة مسارات تقييم مستقلة مقابل الإصدار v0.11.0 — قياس precision/recall التركيبي مقابل الأنماط المعيارية، وفحص DAST واقعي مقابل OWASP Juice Shop، وفحص SAST واقعي مقابل عرض PyGoat لإطار Django ضمن OWASP Top 10. تؤكد المسارات الثلاثة جميعها أن المحرك يكتشف ما يدّعيه، بالكمون الذي ينشره القياس المرجعي، وبالاتساع الذي تحتاجه قواعد الكود الواقعية.
F1 التركيبي
1.000
38 TP / 0 FP / 0 FN عبر 7 فئات كشف
Juice Shop مقابل v0.6.1
+5 CRITICAL
فحص أسرع بنسبة 35 ٪؛ تم الإبلاغ عن كل سطح تسريب إعدادات
PyGoat واقعي
147 نتيجة
12 فئة ثغرة خلال 17 ثانية زمن فعلي
المسار 1 — مجموعة تركيبية موسومة
56 حالة اختبار موسومة عبر 7 فئات كشف. تحتوي كل فئة على متغيرات EXPECT_TP (يجب أن يبلّغ عنها المحرك) ومتغيرات EXPECT_TN (شكل آمن؛ يجب أن يتركها المحرك). تتوفر المجموعة في scripts/accuracy/corpus/؛ والحقيقة المرجعية في scripts/accuracy/manifest.json. تربط أداة التشغيل المخرجات بالحالات الموسومة حسب الفئة + جزء العنوان + الملف + سماحية ±6 أسطر، مع مطابقة أقرب TP غير مُطالَب به بحيث لا يمكن أن يُطالَب بـ TP واحد من قِبل عدة مخرجات.
| الفئة | TP | FP | FN | Precision | Recall | F1 |
|---|---|---|---|---|---|---|
| sqli | 5 | 0 | 0 | 1.000 | 1.000 | 1.000 |
| cmdi | 5 | 0 | 0 | 1.000 | 1.000 | 1.000 |
| path_traversal | 5 | 0 | 0 | 1.000 | 1.000 | 1.000 |
| ssrf | 3 | 0 | 0 | 1.000 | 1.000 | 1.000 |
| open_redirect | 3 | 0 | 0 | 1.000 | 1.000 | 1.000 |
| xss | 4 | 0 | 0 | 1.000 | 1.000 | 1.000 |
| secrets | 13 | 0 | 0 | 1.000 | 1.000 | 1.000 |
| OVERALL | 38 | 0 | 0 | 1.000 | 1.000 | 1.000 |
تحفظ صادق
1.000/1.000/1.000 يعني أن fendix لا يفوّت أبدًا هذه الأنماط المعيارية الـ56 المحددة، وليس أنه لا يفوّت أي شيء على الإطلاق. تقيس المجموعة التركيبية الجانب الإيجابي؛ أما انضباط FP الواقعي مقابل juice-shop والأهداف الإنتاجية فيُتابَع بشكل منفصل في tasks/FP_CORPUS.md ضمن مستودع المحرك. ويؤكد المساران 2 و3 أدناه الملاءمة الواقعية.
إعادة الإنتاج
make build
python3 scripts/accuracy/run.py --python-engine
# Output:
# Running ./bin/fendix scan --code scripts/accuracy/corpus...
# 20 unique findings (40 after exploding affected_endpoints)
#
# CATEGORY TP FP FN TN PREC REC F1
# ----------------------------------------------------------------------
# sqli 5 0 0 3 1.000 1.000 1.000
# cmdi 5 0 0 3 1.000 1.000 1.000
# path_traversal 5 0 0 3 1.000 1.000 1.000
# ssrf 3 0 0 2 1.000 1.000 1.000
# open_redirect 3 0 0 2 1.000 1.000 1.000
# xss 4 0 0 2 1.000 1.000 1.000
# secrets 13 0 0 3 1.000 1.000 1.000
# ----------------------------------------------------------------------
# OVERALL 38 0 0 18 1.000 1.000 1.000تحسينات المحرك التي ظهرت خلال هذا التقييم
أظهرت المجموعة التركيبية، وقمنا بشحن تحسينين فعليين للمحرك + إصلاح كامن واحد للمنسّق، في الجلسة نفسها:
- Open redirect: كان الكاشف يتطلب مباشرًا
redirect(request.args.get("x"))؛ وكانت الإسنادات متعددة القفزات تُفوَّت بصمت. أما المصارف الستة الأخرى القابلة للوصول (SQLi / SSRF / XSS / cmd-injection / path-traversal) فكانت جميعها تطبّق مرشّح ثابت-مقابل-غير-ثابت من TASK-114/120/121/134؛ وكان open-redirect هو مصرف TASK-114 الأصلي ولم يحصل بطريقة ما على معالجة السلسلة. Recall: 0/3 → 3/3. - cmd-injection: تمت مواءمة الوضعية مع المصارف الأخرى القابلة للوصول عبر مساعد جديد
_cmdi_arg_is_dangerous. قبل الإصلاح، كانos.system("echo hello")يطلق HIGH رغم انعدام قابلية الاستغلال (اختار TASK-121 "الإطلاق عند كل استدعاء طرفي"). Precision: 0.833 → 1.000. - المنسّق: يقوم
runWhiteboxScanالآن بحلّcode_pathوspecإلى مسارات مطلقة قبل إرسال ScanRequest. يضبط المُولِّدcmd.Dir = engineDir، لذا كان المسار النسبي يُحَل بصمت إلى لا شيء ضمن مجلد العمل للعملية الابنة. يظهر ذلك على شكل إبلاغ fendix عن 0 نتيجة في قواعد الكود الفعلية — وهو تراجع فعلي معطِّل للمستخدم كامن منذ TASK-118.
المسار 2 — OWASP Juice Shop (DAST واقعي)
أمر fendix scan --url القياسي مقابل bkimminich/juice-shop:v17.1.1. بدون مصادقة، وبدون --code، وبدون --enable-active — مجرد خط المعالجة الافتراضي للصندوق الأسود مقابل القياس المرجعي الحديث لتطبيقات الويب من OWASP.
| المقياس | خط الأساس v0.6.1 | v0.19.0 (الآن) | Δ |
|---|---|---|---|
| إجمالي النتائج (بعد إزالة التكرار) | 7 | 12 | +5 |
| CRITICAL | 0 | 5 | +5 |
| مدة الفحص | 42 s | 27 s | −35 % |
| نقاط النهاية المفحوصة | 97 | 97 | — |
جميع النتائج الخمس الجديدة من فئة CRITICAL هي اكتشافات لملفات إعدادات مكشوفة تم شحنها في TASK-133 (المرحلة 17d): على macOS .DS_Store؛ ملفات البيئة .env / .env.local / .env.production؛ ومكوّنات مستودع Git الداخلية .git/HEAD / .git/config / .git/index؛ وعلى Apache .htaccess + .htpasswd. CWE-538.
تحفظ
Juice Shop هو تطبيق SPA — فكل رابط غير معروف يعيد 200 مع محتوى index.html. قد تكون النتائج الخمس من فئة CRITICAL استجابات احتياطية لـ SPA بدلًا من تسريبات حرفية لملفات الإعدادات. ومع ذلك يظل هذا مشكلة أمان حقيقية: فإن تطبيق SPA الذي يقدّم محتوى متطابقًا لمسارات الإعدادات المعروفة قابل للاستغلال في تسميم التخزين المؤقت، وإرباك WAF، وإرباك المشغّل أثناء الاستجابة للحوادث. يبلّغ Fendix عنها بشكل صحيح؛ وقد تكون المعالجة "اضبط الخادم لإرجاع 404 لهذه المسارات" بدلًا من "تدوير السر المسرَّب."
إعادة الإنتاج
JS_PORT=3001 FENDIX_BIN=./bin/fendix bash scripts/benchmark/run-juice-shop.sh
# Output (bench-results/juice-shop/<timestamp>/):
# Fendix benchmark — OWASP Juice Shop
# Fendix version: fendix v0.11.0 (darwin/arm64)
# Target image: bkimminich/juice-shop:v17.1.1
# Scan duration: 27 seconds
# Endpoints: 97
# Total findings: 12
#
# By severity: CRITICAL: 5 HIGH: 0 MEDIUM: 4 LOW: 2 INFO: 1المسار 3 — PyGoat (SAST واقعي)
نسخة من adeyosemanputra/pygoat — تطبيق Django مصمَّم ليكون قابلًا للاستغلال في كل فئة من OWASP Top 10. 52 ملف Python بالإضافة إلى أصول JavaScript. الفحص عبر fendix scan --code /tmp/pygoat --python-engine دون مصادقة أو فحص نشط.
إجمالي النتائج
147
1 CRITICAL · 146 HIGH
مدة الفحص
17.1 s
52 ملف Python + أصول JS
الفئات المكتشفة
12
كل فئة من OWASP Top 10 يعلن عنها PyGoat
| الخطورة | فئة الثغرة | أول اكتشاف |
|---|---|---|
| CRITICAL | Unsafe pickle deserialization (RCE) | dockerized_labs/insec_des_lab/main.py:36 |
| HIGH | Unsafe eval() with dynamic arg | introduction/mitre.py:218 |
| HIGH | subprocess(shell=True) | introduction/mitre.py:233 |
| HIGH | Unsafe yaml.load() (RCE) | introduction/lab_code/test.py:23 |
| HIGH | SSRF — dynamic URL | 2 sites (incl. views.py:963) |
| HIGH | innerHTML XSS | introduction/static/js/a9.js:40 |
| HIGH | Open redirect — 9 sites | broken_auth_lab/app.py:107 |
| HIGH | Hardcoded API key / password / JWT | 3 distinct files |
| HIGH × 133 | Vulnerable dependency (certifi, cryptography, django, …) | requirements.txt |
تحفظات
- لا يوجد بيان حقيقة مرجعية لـ PyGoat. يوثّق PyGoat دروس OWASP Top 10 لكنه لا يوفّر بيانًا قابلًا للقراءة آليًا بمستوى الأسطر. لا يمكننا حساب precision/recall هنا — بل فقط تأكيد اكتشاف كل فئة يعلن عنها PyGoat. وهذه ملاءمة واقعية نوعية، وليست رقمًا كميًّا.
- العدد المرتفع مقصود بالتصميم. PyGoat قابل للاستغلال عمدًا؛ و147 نتيجة على قاعدة كود من 52 ملفًا هي الشكل المتوقع، وليست مشكلة ضوضاء. ستنتج قواعد الكود الإنتاجية نتائج قريبة من الصفر — وهذا هو الغرض من مسار قياس مجموعة FP.
إعادة الإنتاج
git clone --depth 1 https://github.com/adeyosemanputra/pygoat /tmp/pygoat
./bin/fendix scan --code /tmp/pygoat --python-engine --max-duration 60s
# Output:
# scan complete duration=17.082s total=147 critical=1 high=146 medium=0
#
# By category:
# deps 135 (real CVE-tagged dependencies in requirements.txt)
# injection 9 (SSRF/XSS/eval/subprocess-shell/pickle/yaml/open-redirect)
# secrets 3 (hardcoded API key, password, JWT)تعمّق أكثر
- docs/accuracy.md — المصدر الأساسي لكل رقم في هذه الصفحة (يُحافَظ على مزامنته).
- /performance — كمون بدء التشغيل البارد + قياس حجم الملف الثنائي.
- scripts/accuracy/run.py — أداة التشغيل. نحو 250 سطر كود، تُقرأ بوضوح من الأعلى إلى الأسفل.
- tasks/FP_CORPUS.md — مجموعة انضباط FP الواقعية (juice-shop، fendix-self، TwiScope). الوجه الآخر لهذه الصفحة: ما لا يكتشفه fendix / ما يبلّغ عنه بالخطأ.