نظرة عامة على النظام
يجمع محرك Fendix بين محللات أمن التطبيقات وجامعي الأدلة. وتستخدم Fendix الأدلة التي تنتجها، مع الأدلة المستوردة، لتقييم التغطية المطلوبة وإصدار قرارات إصدار تحكمها السياسة. تعمل محللات Go الأصلية من الملف التنفيذي الواحد، ويحاول فحص الشيفرة تشغيل محرك الصندوق الأبيض المكتوب بـ Python تلقائيًا. لا تتضمن الملفات التنفيذية المستقلة شجرة Python، بينما تتضمنها صورة Docker الرسمية. استخدم --python-engine لاشتراط المحرك وجعل غيابه سببًا للخروج برمز 2، أو --python-engine=false للمسار الأصلي فقط. ويظل عقد JSON المفصول بأسطر (ADR-002) ساريًا لعمليات Python والإضافات الفرعية.
User CLI Command
|
v
+----------------------------------+
| Go Binary |
| - CLI (cobra) |
| - HTTP Scanner (black-box) | Sends real HTTP requests
| - Orchestrator |
| - Correlator |
| - Reporters |
| - Textscan (native Go) | Go / JS / Java / IaC rules
| |
| In-process Go scanners: |
| - Secrets (TASK-115) | 18 detectors including ENV_SECRET
| - Dep CVE (TASK-119) | govulncheck / pip / npm
| - Plugin runtime (TASK-113) | NDJSON IPC subprocess
+----------------+-----------------+
|
| shells out to host binary
v
+-------------------+
| semgrep (host) | TASK-116 — graceful absence
+-------------------+
|
| --code auto-attempts; explicit flag requires
v
+-------------------+
| Python Engine | Not bundled in standalone binaries
| - Spec Parser | Local python/ or FENDIX_ENGINE;
| - AST Analyzer | Docker ships /opt/fendix/python
| - Auth checks |
+-------------------+ADR-001: بنية هجينة بلغتي Go و Python
مقبول (المرحلة 0)؛ تطوّر في v0.9 / المرحلة 17bالسياق
يحتاج Fendix إلى قدرتين مختلفتين جوهريًا: فحص HTTP من نوع black-box (تزامن عالٍ، زمن استجابة منخفض، توزيع كملف تنفيذي واحد) والتحليل الساكن من نوع white-box (كُتب أصلًا بلغة Python لأن منظومة أدوات الأمان فيها — Semgrep و Bandit و detect-secrets — كانت متقدمة بعام عن أي مكافئ في Go). ولم تتفوق أي لغة واحدة في كليهما.
القرار (المرحلة 0 — من v0.1 حتى v0.8)
- Go لواجهة CLI وماسح HTTP والمنسّق والمرتبط ومُصيّر التقارير. يُترجم إلى ملف تنفيذي واحد مع بدائيات تزامن ممتازة.
- Python لمحرك التحليل الساكن، مضمّن في الملف التنفيذي عبر
//go:embedويُستخرج إلى~/.fendix/engine/عند أول تشغيل. يُشغّل كعملية فرعية. يحمل فحوص Semgrep والأسرار وتحليل AST وثغرات تبعيات CVE. - الاتصال عبر JSON مفصول بأسطر عبر stdin/stdout (انظر ADR-002 أدناه).
التطور منذ v0.9 / المرحلة 17b — لم تعد الملفات التنفيذية المستقلة تضمّن Python
لا يزال ADR-001 مقبولًا لفصل المسؤوليات بين Go وPython، بينما تطوّر نموذج توزيعه. فقد نضجت منظومة ماسحات Go (يوفّر govulncheck قابلية الوصول عبر رسم استدعاءات الدوال؛ ومعالجة التعبيرات النمطية كافية للأسرار)، وتجاوزت كلفة تضمين Python — حجم التثبيت وزمن البدء البارد وأسئلة الدعم — الفائدة المرجوة. تنقل المرحلة 17b مسارات الأسرار وSemgrep إلى Go أصيلة ( internal/scanner/secrets/، internal/scanner/semgrep/ يستدعي الملف التنفيذي المتاح)، وتُسقط توزيعة Python المضمّنة من الإصدارات المستقلة. تحاول فحوصات الشيفرة الحالية تشغيل محرك Python الخارجي تلقائيًا؛ وتؤدي الراية --python-engine إلى اشتراطه وجعل غيابه سببًا للخروج برمز 2. ويبقى عقد IPC من ADR-002 دون تغيير.
- انخفض البدء البارد الافتراضي إلى ~5.6 مللي ثانية p50 (كان ~7.3 مللي ثانية في v0.8).
- لا تحتاج المحللات الأصلية إلى مفسّر Python يمكن لفحوصات الشيفرة المستقلة العمل دون Python وتسجيل غياب المحرك الاختياري كفجوة تغطية، أو تعطيل محاولة تشغيله صراحةً.
- نفس شكل النتيجة عبر الانتقال —
SEC-*المعرّفات ودرجات الخطورة والمراجع كلها متطابقة بايتًا ببايت؛ وتستوعب خطوط الإدخال القائمة النتائج الجديدة دون تغيير.
النتائج الإيجابية (لا تزال قائمة)
- أفضل أداة لكل مهمة — Go للشبكات، وتبقى Python خيارًا للتحليل المعتمد بكثافة على AST
- توزيع كملف تنفيذي واحد لواجهة CLI (لم تعد Python مضمّنة)
- يبقى محرك Python الاختياري قابلًا للتشغيل المستقل لأغراض تصحيح الأخطاء
- فصل واضح للمسؤوليات بين المحركات عبر عقد NDJSON IPC (لا يزال أساسيًا للإضافات)
- لا يزال بالإمكان اختبار كل محرك بشكل مستقل
المقايضات وإجراءات التخفيف
- منظومتا لغتين للصيانة (وحدات Go + pip عند توفر محرك Python)
- يضيف بدء عملية Python الفرعية زمنًا مقيسًا كلما عمل ذلك المحرك
- تتطلب الراية الصريحة
--python-engineشجرة Python محلية وتجعل الغياب سببًا للخروج برمز 2؛ أما تعذّر المحرك الضمني فهو فجوة تغطية - عقد IPC موثّق ومختبَر من طرف إلى طرف في CI
ADR-002: عقد IPC بصيغة JSON مفصول بأسطر
مقبولالسياق
يحتاج منسّق Go إلى التواصل مع محرك Python. ويجب أن يكون البروتوكول بسيطًا وقابلًا لتصحيح الأخطاء وقابلًا للبث وموثوقًا.
الخيارات المدروسة: gRPC (معقّد للغاية)، مقبس Unix + JSON-RPC (عبء إدارة المقبس)، JSON مفصول بأسطر عبر stdin/stdout (الأبسط).
مخطط IPC
ScanRequest (Go → Python stdin)
{
"mode": "whitebox",
"spec": "./openapi.yaml",
"code_path": "./src/",
"language": "python",
"checks": ["secrets", "auth", "injection", "semgrep", "deps"],
"verbose": false
}Finding (Python → Go stdout، واحدة لكل سطر)
{
"id": "SEC-001",
"title": "Hardcoded API key detected",
"severity": "CRITICAL",
"source": "whitebox",
"category": "secrets",
"endpoint": "src/config.py:14",
"evidence": "API_KEY = [REDACTED len=40 sha256:1f4a9c2e...]",
"fix": "Move to environment variable. Rotate the exposed key immediately.",
"references": ["CWE-798"],
"confidence": "HIGH",
"line": "src/config.py:14"
}منهي البث (السطر الأخير)
{"done": true, "total": 12}النتائج الإيجابية
- صفر تبعيات — JSON و stdin/stdout موجودان في كل لغة
- قابل للبث — تظهر النتائج في Go فور اكتشافها بواسطة Python
- قابل لتصحيح الأخطاء — مرّره إلى jq أو cat للفحص
- محرك Python قابل للاختبار بشكل مستقل
- بلا منافذ شبكية أو مقابس أو إدارة اتصالات
المقايضات وإجراءات التخفيف
- لا تحقق من المخطط على مستوى البروتوكول (يُخفَّف عبر الاختبارات)
- لا اتصال ثنائي الاتجاه أثناء الفحص
- تُقتطع حقول الأدلة إلى 200 حرف كحد أقصى
- اختبارات العقد من طرف إلى طرف تُجرى في CI
تحديد الخطورة النهائية ومدخلات القرار
يُسند كل فحص خطورة أصلية منفصلة. وقد يرفعها الترابط المؤهل أو المسار المثبت أو قابلية الوصول المثبتة في SAST، ثم تضع الثقة حدًا للخطورة النهائية. تقيّم السياسة هذه النتيجة إلى جانب الثقة والأدلة والتغطية. ومع تفعيل فرض الثقة، وهو الوضع الافتراضي، لا تنتج الخطورة وحدها حالة BLOCK؛ ويعيد الخيار --enforce-confidence=false بوابة الخطورة وحدها القديمة.
الخطورة النهائية عند دخول بوابة القرار
1. يُسند الفحص التنفيذي خطورة أصلية منفصلة.
2. قد يرفعها الترابط أو المسار المثبت أو قابلية الوصول المثبتة في SAST.
3. تضع الثقة حدًا للنتيجة: LOW عند MEDIUM، وMEDIUM عند HIGH.
4. تقارن --fail-on هذه الخطورة النهائية بالحد المضبوط.
مع تفعيل فرض الثقة (الوضع الافتراضي)، لا تنتج الخطورة وحدها BLOCK. وتظل درجة
الثقة والأدلة الداعمة وحالة التغطية والسياسة مدخلات مستقلة للقرار. ويعيد الخيار
--enforce-confidence=false بوابة الخطورة وحدها القديمة.