تخطٍّ إلى المحتوى

الدقة والاختبارات المعيارية

نوعان من النتائج، كلٌّ منهما موسوم بإصدار المحرك الذي أنتجه: قياس حالي على المجموعة الاصطناعية للمحرك (v3.6.3)، وملاحظات تاريخية على أهداف واقعية (v0.11.0). ولا يمثّل أيٌّ منهما دقة أو استدعاء في بيئات الإنتاج.

القياس الحالي — إصدار المحرك v3.6.3

المجموعة الاصطناعية الموسومة في مستودع المحرك، مُشغَّلة بأداة القياس من وسم الإصدار نفسه داخل صورة v3.6.3 الرسمية، مع تعطيل الشبكة.

الإجمالي: 38 إيجابية صحيحة، و0 إيجابية خاطئة، و0 سلبية خاطئة، و18 سلبية صحيحة — دقة واستدعاء وF1 بقيمة 1.000 عبر 7 فئات.

المصدر

  • Fendix v3.6.3، إيداع المحرك c491c80a
  • الصورة fendixapp/fendix@sha256:2a3b25df…fb9fad، وهي صورة الإصدار v3.6.3 الرسمية
  • المجموعة والبيان من الوسم v3.6.3 (56 حالة موسومة، شجرة git ‏995d4eb8)
  • قيس في 10 أكتوبر 2026
  • Docker على معالج Apple (linux/arm64)، دون شبكة
  • 4 تشغيلات بنتائج متطابقة

ما الذي يُظهره هذا وما الذي لا يُظهره

تصف هذه النتائج هذه المجموعة المضبوطة وحدها، وليست مقياسًا للدقة في بيئات الإنتاج. فهي تُظهر أن الإصدار ما زال يلتقط كل نمط في مجموعة الانحدار الخاصة به ولا يبلّغ عن أيٍّ من الحالات الآمنة. ولا تقيس الدقة أو الاستدعاء على قواعد شيفرة واقعية، ولا تقول شيئًا عن DAST أو فحص الاعتماديات، كما أن هذه المجموعة بوابة في CI للمحرك، فالنتيجة الكاملة هي الحالة المتوقعة لا اكتشاف. ولم يُعَد تشغيل المسارات الواقعية أدناه على v3.6.3.

إعادة الإنتاج

git clone --depth 1 --branch v3.6.3 https://github.com/Fendix-app/Fendix.git fendix-v3.6.3
mkdir -p out && chmod 0777 out
docker run --rm --network none \
  -v "$PWD/fendix-v3.6.3/scripts/accuracy":/bench:ro -v "$PWD/out":/out \
  --entrypoint python3 fendixapp/fendix@sha256:2a3b25df2b52e1bd9a5a4c7d82cf56ad9536a57a238e37ee264fd2eb1efb9fad \
  /bench/run.py /usr/local/bin/fendix --python-engine --output-json /out/run.json

نتائج تاريخية — إصدار المحرك v0.11.0

سُجّلت في مايو 2026 على إصدار المحرك 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 نتيجة وفق السياسة والتغطية المحددتين وليست ضمانًا للأمان أو موافقة بشرية.

الجداول أدناه ملاحظات تاريخية من المحرك v0.11.0. أما نتيجة v3.6.3 أعلاه فقياس مضبوط على المجموعة الاصطناعية للمحرك. ولا تمثّل أيٌّ منهما دقة أو استدعاءً في بيئة الإنتاج.

اقرأ معالجة البيانات حسب طريقة النشر

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 واحد من قِبل عدة مخرجات.

الفئةTPFPFN‏Precision‏RecallF1
sqli5001.0001.0001.000
cmdi5001.0001.0001.000
path_traversal5001.0001.0001.000
ssrf3001.0001.0001.000
open_redirect3001.0001.0001.000
xss4001.0001.0001.000
secrets13001.0001.0001.000
OVERALL38001.0001.0001.000

تحفظ صادق

‏1.000/1.000/1.000 يعني أن fendix لا يفوّت أبدًا هذه الأنماط المعيارية الـ56 المحددة، وليس أنه لا يفوّت أي شيء على الإطلاق. تقيس المجموعة التركيبية الجانب الإيجابي؛ أما انضباط FP الواقعي مقابل juice-shop والأهداف الإنتاجية فيُتابَع بشكل منفصل في tasks/FP_CORPUS.md ضمن مستودع المحرك. أما المساران 2 و3 فهما ملاحظات تاريخية، وليسا قياسًا محكّمًا للدقة أو الاستدعاء في بيئات الإنتاج.

إعادة الإنتاج

terminal
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.1v0.11.0 (تاريخي)Δ
إجمالي النتائج (بعد إزالة التكرار)712+5
CRITICAL05+5
مدة الفحص42 s27 s−35 %
نقاط النهاية المفحوصة9797—

صنّف التشغيل التاريخي خمس نتائج كحرجة. لم يُتحقق من كون الاستجابات تحتوي ملفات حساسة؛ لا نعدّها تسريبات مؤكدة.

تحفظ

قد تُعيد تطبيقات SPA الصفحة نفسها لمسارات غير موجودة. استجابة HTTP 200 وحدها لا تثبت تسرب ملف أو تسميم ذاكرة التخزين المؤقت. يلزم فحص المحتوى ومقارنته بمسار عشوائي قبل إثبات الخطر.

إعادة الإنتاج

terminal
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

فئات رُصدت في التشغيل التاريخي

الخطورةفئة الثغرةأول اكتشاف
CRITICALUnsafe pickle deserialization (RCE)dockerized_labs/insec_des_lab/main.py:36
HIGHUnsafe eval() with dynamic argintroduction/mitre.py:218
HIGHsubprocess(shell=True)introduction/mitre.py:233
HIGHUnsafe yaml.load() (RCE)introduction/lab_code/test.py:23
HIGHSSRF — dynamic URL2 sites (incl. views.py:963)
HIGHinnerHTML XSSintroduction/static/js/a9.js:40
HIGHOpen redirect — 9 sitesbroken_auth_lab/app.py:107
HIGHHardcoded API key / password / JWT3 distinct files
HIGH × 133Vulnerable dependency (certifi, cryptography, django, …)requirements.txt

تحفظات

  • لا يتوفر بيان حقيقة مرجعي على مستوى النتائج لهذا التشغيل؛ لا يمكن حساب precision أو recall منه.
  • عدد النتائج لا يقيس الدقة. لا تسمح هذه التجربة باستنتاج عدد النتائج أو الإيجابيات الكاذبة في تطبيقات الإنتاج.

إعادة الإنتاج

terminal
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 / ما يبلّغ عنه بالخطأ.