الدقة
نتائج تاريخية محدودة النطاق للمحرك v0.11.0، وليست قياسًا لدقة الإصدار الحالي. تتطلب المقارنة الحديثة إعادة تشغيل موثقة ومراجعة النتائج.
نطاق التنفيذ الحالي
- بيئة التشغيل
- لا تتطلب ملفات Go التنفيذية الجاهزة مترجم Go للفحص الأساسي. يتطلب البناء من المصدر Go 1.25+. لمحركات الفحص الاختيارية متطلبات تشغيل خاصة؛ راجع التغطية للتأكد من تنفيذها.
- DAST
- يفحص تحليل الروابط وواجهات API السلوك الظاهر أثناء التشغيل. تتطلب الاختبارات النشطة --enable-active. لا تثبت استجابة HTTP 200 وحدها الوصول إلى بيانات حساسة.
- SAST
- تغطي القواعد الساكنة الأصلية أنماطًا مدعومة في Go وJavaScript وJava والبنية التحتية. يوسع Semgrep ومحرك Python الاختياري الفحوصات المناسبة. دعم اللغة لا يعني تغطية جميع الأطر أو المسارات.
- SCA
- يستخدم تحليل Go أداة govulncheck. تستخدم محركات تبعيات Python وnpm ملفات التعريف والتثبيت المدعومة، ومنها poetry.lock وPipfile.lock وpackage-lock.json. قد تنقل استعلامات الثغرات أسماء الحزم وإصداراتها.
- الأدلة والسياسة
- يربط الترابط المشاهدات المتطابقة المدعومة؛ ليست لكل نتيجة مصادر متعددة. قد تكفي أدلة قوية من مصدر واحد. الشدة والثقة وحالة النتيجة وتوصية الإصدار مفاهيم منفصلة.
- التغطية والمراجعة البشرية
- قد يترك فشل محرك أو غياب أدلة مطلوبة الإصدار غير مكتمل. تعني PASS نتيجة وفق السياسة والتغطية المحددتين وليست ضمانًا للأمان أو موافقة بشرية.
جداول القياس أدناه ملاحظات تاريخية محددة النطاق. أعداد النتائج ودرجات الاختبارات الاصطناعية ليست مقاييس الدقة والاستدعاء في الإنتاج. لا ندعي وجود قياسات بديلة هنا.
اقرأ معالجة البيانات حسب طريقة النشرF1 التركيبي
1.000
38 TP / 0 FP / 0 FN عبر 7 فئات كشف
Juice Shop مقابل v0.6.1
غير مُتحقق منها
الاستجابات العامة للتطبيق لا تثبت تسرب الملفات.
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) فكانت جميعها تطبّق مرشّح ثابت-مقابل-غير-ثابت من تغيير سابق؛ وكان open-redirect هو مصرف تغيير سابق الأصلي ولم يحصل بطريقة ما على معالجة السلسلة. Recall: 0/3 → 3/3. - cmd-injection: تمت مواءمة الوضعية مع المصارف الأخرى القابلة للوصول عبر مساعد جديد
_cmdi_arg_is_dangerous. قبل الإصلاح، كانos.system("echo hello")يطلق HIGH رغم انعدام قابلية الاستغلال (اختار تغيير سابق "الإطلاق عند كل استدعاء طرفي"). Precision: 0.833 → 1.000. - المنسّق: يقوم
runWhiteboxScanالآن بحلّcode_pathوspecإلى مسارات مطلقة قبل إرسال ScanRequest. يضبط المُولِّدcmd.Dir = engineDir، لذا كان المسار النسبي يُحَل بصمت إلى لا شيء ضمن مجلد العمل للعملية الابنة. يظهر ذلك على شكل إبلاغ fendix عن 0 نتيجة في قواعد الكود الفعلية — وهو تراجع فعلي معطِّل للمستخدم كامن منذ تغيير سابق.
المسار 2 — OWASP Juice Shop (DAST واقعي)
أمر fendix scan --url القياسي مقابل bkimminich/juice-shop:v17.1.1. بدون مصادقة، وبدون --code، وبدون --enable-active — مجرد خط المعالجة الافتراضي للصندوق الأسود مقابل القياس المرجعي الحديث لتطبيقات الويب من OWASP.
| المقياس | خط الأساس v0.6.1 | v0.11.0 (تاريخي) | Δ |
|---|---|---|---|
| إجمالي النتائج (بعد إزالة التكرار) | 7 | 12 | +5 |
| CRITICAL | 0 | 5 | +5 |
| مدة الفحص | 42 s | 27 s | −35 % |
| نقاط النهاية المفحوصة | 97 | 97 | — |
صنّف التشغيل التاريخي خمس نتائج كحرجة. لم يُتحقق من كون الاستجابات تحتوي ملفات حساسة؛ لا نعدّها تسريبات مؤكدة.
تحفظ
قد تُعيد تطبيقات SPA الصفحة نفسها لمسارات غير موجودة. استجابة HTTP 200 وحدها لا تثبت تسرب ملف أو تسميم ذاكرة التخزين المؤقت. يلزم فحص المحتوى ومقارنته بمسار عشوائي قبل إثبات الخطر.
إعادة الإنتاج
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
فئات رُصدت في التشغيل التاريخي
| الخطورة | فئة الثغرة | أول اكتشاف |
|---|---|---|
| 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 |
تحفظات
- لا يتوفر بيان حقيقة مرجعي على مستوى النتائج لهذا التشغيل؛ لا يمكن حساب precision أو recall منه.
- عدد النتائج لا يقيس الدقة. لا تسمح هذه التجربة باستنتاج عدد النتائج أو الإيجابيات الكاذبة في تطبيقات الإنتاج.
إعادة الإنتاج
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 / ما يبلّغ عنه بالخطأ.