الأمان والسلامة
نموذج سلامة كاظمه: ثلاثة مسارات تنفيذ HITL + سجلّ بوابات واحد، ومستويات أدوات بالرفض الافتراضي، وناقل فاشل-مغلق، وCSRF / الوكلاء الموثوقون، وتثبيت IP لـ SSRF، ومهارات HMAC، والتحصين. الثوابت:
AGENTS.md§7، §26، §30–§32.
راجع أيضًا: أمان المستندات — استيعاب عدائي،
وملفّا تعريف عزل العامل (process، الذي لا يحصر نظام الملفات ولا الشبكة،
وملف container الموثَّق لكل مهمة)، وتسييج، ومسح برمجيات خبيثة،
وخروج التحليل البعيد، ونموذج إخفاء بيانات لذكاء المستندات.
1. ثلاثة مسارات تنفيذ HITL + سجلّ واحد
Section titled “1. ثلاثة مسارات تنفيذ HITL + سجلّ واحد”تملك كاظمه ثلاثة مسارات تنفيذ HITL مستقلة. يغطّي كلٌّ منها مسارًا مختلفًا
لتشغيل الأدوات. وكسر أيٍّ منها يُنشئ فجوة أدوات خطيرة بلا مُراقِب.
حقيقة القرار قطعة رابعة: سجلّ بوابات HITL
(kazma-data/hitl_gates.db). وتبقى حقيقة التنفيذ في الـ checkpoint الخاص بـ
LangGraph (أو SQLite لخط المعالجة). الأسطح تعرض؛ وهي لا تستنتج أبدًا
«مُوافَق عليه» من صف غائب.
flowchart TB
subgraph "Path A: Graph interrupt (single-agent chat)"
A1[graph_tool_worker.tool_worker_node] -->|danger + hitl_config| A2[interrupt]
A2 --> REG[hitl_gates.db CAS]
REG -->|resume Command| A3[execute with _hitl_approved]
end
subgraph "Path B: Swarm bus (/swarm + IDE execute)"
B1[LocalToolRegistry.execute] --> B2[SafetyMiddleware.check]
B2 -->|register_gate| REG
B2 --> B3[bus.request_approval]
B3 -->|FanOut tri-state| B4[claim + settle]
end
subgraph "Path C: Pipeline checkpoints"
C1[pipeline HITL step] --> C2[CheckpointManager]
C2 --> REG
C2 -->|approve_checkpoint| C4[resume_pipeline]
end
| المسار | مكان وجوده | سطح الموافقة |
|---|---|---|
| A | agent/graph_tool_worker.py (موصَّل من graph_builder.py) | POST /api/approve/{thread_id} (routes_direct/misc.py) أو بوابة /hitl approve|deny |
| B | swarm/safety.py + tool_registry.py | أزرار محوّل الناقل (Telegram / Discord / Slack) |
| C | swarm/checkpoint_manager.py | POST /api/swarm/tasks/{id}/approve |
تتطلب قرارات /hitl في البوابة مشرفًا يملك خيط المحادثة المستهدف. تُحفظ
الملكية في دليل الجلسات بصورة دائمة، مستقلة عن خبيئة التسليم لخمس دقائق،
فتنجو الموافقات المصرّح بها من انتهاء الخبيئة وإعادة التشغيل. تُرفض الهوية
المفقودة أو غير المطابقة قبل قراءة الرسم. ولا يستطيع أمر الموافقة إنشاء
ملكية خيطه. عند ضبط KAZMA_GATEWAY_ADMINS تكون قائمته نافذة؛ وإلا تمنح
قائمة المستخدمين المسموحين للمنصة صلاحية المشرف. تتيح القائمة الفارغة
الدردشة دون منح أي صلاحية مشرف.
يتطلب تفعيل /yolo أو /unrestricted أو /long yolo مشرف بوابة أيضًا.
تفحص المعالجات التفويض قبل التفعيل؛ وإضافة أسمائها إلى بوابة أوامر لاحقة
تتركها بلا حماية. يبقى فحص الحالة وتعطيل YOLO متاحين دون منح صلاحيات جديدة.
وتسري قيود YOLO الإنتاجية على المشرفين أيضًا.
ليست بوابات HITL إضافية:
- خطافات الأدوات (
agent/tool_hooks.py) — لا تستطيع الموافقة تلقائيًا على الخطر، ولا تخطّي الالتزام، ولا استبدال قائمة YAML. الخطاف المكسور يفشل مفتوحًا.KAZMA_TOOL_HOOKS=0. - وضع التخطيط —
/plan onيزيل أدوات الكتابة/التنفيذ. و/plan goيعيدها؛ والخطر ما يزال يتطلّب موافقة. - توضيح/تأكيد الالتزام — ناقل المقاطعة نفسه، لكن بـ
kindمختلف (أدناه).
حرِج: hitl_config في كل رسم بياني قابل للاستئناف
Section titled “حرِج: hitl_config في كل رسم بياني قابل للاستئناف”لا تُفعَّل البوابة إلا عند تمرير hitl_config إلى build_supervisor_graph(). القارئ الحيّ: get_hitl_config(). المهلة الافتراضية في YAML هي 300 ثانية.
| موقع البناء | HITL؟ | ملاحظات |
|---|---|---|
KazmaAgent._ensure_graph() | ✅ | مسار التشغيل؛ مع checkpointer كي يستطيع interrupt() الاستئناف |
إعادة التجميع عند بدء التشغيل في app.py داخل _graph_holder | ✅ | SSE SoT — checkpointer + HITL. حذفه = بوابة ويب خاملة |
KazmaAgent.get_streaming_graph() | ⚠️ auto_deny | مُخزَّن مؤقتًا بدون checkpointer (متزامن). لا يستطيع مستهلكو نافذة الصوت/الإقلاع استئناف interrupt()، لذا الأدوات الخطيرة ترفض بدل خلق توقّف لا يمكن استئنافه |
لا يوجد أي مصنع create_supervisor_graph(). لا تثبّت أرقام أسطر app.py.
H-8: يجب ألا يُنشئ LocalToolRegistry.execute على مسار الويب/المحادثة بوابةً ثانية. تتجاوز ContextVars الخاصة بالرسم (_graph_hitl_gate_ctx / _hitl_approved_ctx) إعادة مطالبة الناقل. التوضيح/التأكيد القادمان من execute() يفشلان مغلقين («شغِّل من المحادثة»).
2. المسار A — بوابة الرسم البياني (محادثة الوكيل الواحد)
Section titled “2. المسار A — بوابة الرسم البياني (محادثة الوكيل الواحد)”2.1 كيف تعمل
Section titled “2.1 كيف تعمل”يعيش tool_worker_node في graph_tool_worker.py، وليس في graph_builder.py. عندما يُزوَّد hitl_config:
- لا تحصل على بطاقة أيُّ استدعاءٍ سيرفضه المضيف على أي حال:
shell_execترفضه سياسة صدفة المضيف، أو أمر فارغ أو محرف صدفة خاص؛ أو أداة متصفح أوcomputer_useلا يستطيع هذا المضيف تشغيلها (safety/call_preflight.call_refusal). يتلقى النموذج خطأً عاديًا ويستمر الدور. - يعمل
authorize_effectالخاص بالالتزام أولًا (قد يعيد كتابة الوسائط أو يرفع بطاقة دلالية). - تُختبَر كل أداة عبر
requires_approval(name, hitl_config)(safety/hitl.py). الأدوات غير المصنَّفة تبقى خلف البوابة (TOOL_TIERS؛ رفض افتراضي F-04). - تستدعي الأدوات الخطيرة
interrupt()الخاص بـ LangGraph — فيُعلَّق الرسم البياني. ويُسجَّل صف في السجلّ (pending). - عند الموافقة، يُحقَن
_hitl_approvedكي لا يعيدexecute()مطالبة الناقل. والسجلّ يطالب ثم يسوّي. - عند الرفض، يُعاد
ToolResultمعis_error=True. تنتهي صلاحية الموافقة التي لا يجيب عنها أحد خلالapproval_timeout_seconds: لا تُشغَّل الأداة، ويُبلَّغ النموذج بأن البطاقة أُغلقت وأن أحدًا لم يقرّر، وينتهي الدور بإجابة تقول ذلك.
إذا كان hitl_config خاطئ القيمة (falsy)، تتخطى جميع الأدوات هذه البوابة. لهذا يجب أن يمرّره كل موقع بناء قابل للاستئناف.
يرسم الويب من _serverGates / TurnDocument (chat.js). يُبقي close_turn الدور مفتوحًا ما دام صف pending موجودًا. وغياب الصف بوابة معلّقة غير مُسجَّلة (استرجاع)، وليس أبدًا ختم «مُوافَق عليه» مُستنتَجًا.
المصادقة: KAZMA_SECRET مقابل الجلسات المُبهَمة
Section titled “المصادقة: KAZMA_SECRET مقابل الجلسات المُبهَمة”لا تعتمد أبدًا على KAZMA_SECRET القائم على الكوكيز لأمان تعدد المستخدمين. كوكي kazma-secret=<KAZMA_SECRET> هو السرّ المشترك الخام: سرقته = صلاحيات مدير حتى التدوير؛ لا جدول إبطال؛ ولا هوية لكل مستخدم.
استخدم جلسات مُبهَمة على جانب الخادم (kazma-session مُعرِّف عشوائي ← صف مُجزَّأ + انتهاء صلاحية). وأبقِ KAZMA_SECRET لمصادقة الترويسة بين الآلات. إن لم يُضبط، فقد يُعيد get_kazma_secret() سلسلة فارغة "" وتصبح نقاط نهاية الموافقة غير مُصدَّقة — اضبطه دائمًا خارج localhost.
خلف وكيل عكسي، عنوان النظير ليس اعتمادًا. اضبط KAZMA_TRUSTED_PROXIES. لا تُطِع X-Forwarded-* إلا من تلك العناوين. الوكيل غير المُعلَن يُطلق undeclared_proxy_detected() ويسحب ثقة النظير من العملية (AGENTS.md §26A). يجب أن يستخدم تحديد المعدل / خنق تسجيل الدخول auth.client_address(request)، لا request.client.host.
لا تطبع مخرجات أول تشغيل السر المولّد. يستطيع المشغّل المحلي فتح واجهة
loopback؛ واضبط KAZMA_SECRET قويًا في .env الخاص بالتثبيت للحصول على
اعتماد ثابت للآلة.
2.2 الاستئناف
Section titled “2.2 الاستئناف”POST /api/approve/{thread_id} (kazma_ui/routes_direct/misc.py الدالة approve_tool) — وليس app.py. يطالب بصف السجلّ، ثم ينفّذ graph.ainvoke(Command(resume=…), config). عدم تطابق الملكية ← 403. لا يقبل WebSocket أي موافقة (يرفض approve_tool).
تبقى الأدوار المعلّقة في مخزن نقاط الحفظ. عند إقلاع المالك الحصري،
يحجز boot_sweep() الصفوف التي انقطع حجزها أو استئنافها كأخطاء تنفيذ، مع
حفظ القرار وصاحبه. ولا يمس الصفوف المعلّقة أبدًا؛ يجب أن تنجو البطاقة
من إعادة التشغيل. لا يظهر الاستئناف الفاشل كموافقة، ولا يعيد فتح البطاقة
نفسها. تحجز إيصالات أدوات الرسم الآثار المجهولة للفحص؛ ولا تجيز إعادة
المحاولة التلقائية.
3. المسار B — بوابة ناقل السرب (/swarm + IDE)
Section titled “3. المسار B — بوابة ناقل السرب (/swarm + IDE)”3.1 مسار التنفيذ
Section titled “3.1 مسار التنفيذ”LocalToolRegistry.execute():
- يُخرج
_hitl_approved. - إن لم يكن مُوافَقًا عليه سلفًا، يستدعي
get_safety(). - يجب أن يستدعي
is_danger_tool(name)الدالةrequires_approval()(H-9 — أرضية المستوى، لا قائمة أسماء يمكن أن تفتح البوابة بالإغفال). await safety.check(...). الرفض ←is_error=True.- فشل-مغلق: أي استثناء في فحص السلامة ← حجب.
3.2 SafetyMiddleware
Section titled “3.2 SafetyMiddleware”swarm/safety.py — الصنف SafetyMiddleware (وليس SafetyGate / SafetyChecker).
| الدالة | السلوك |
|---|---|
check() (لامتزامنة) | الأدوات الخطيرة: NullBus + allow_headless_danger=False ← رفض؛ وإلا bus.request_approval |
check_sync() | فشل-مغلق. لا يستطيع المسار المتزامن الانتظار على ناقل؛ يحجب إلا مع مخرج headless |
is_danger_tool | التصنيف عبر requires_approval / TOOL_TIERS / ALWAYS_HITL_TOOLS |
allow_headless_danger=False هو الافتراضي. تضبطه الاختبارات/التطوير على true. لا تفعل ذلك في الإنتاج.
قائمة الخطر: _EXTENDED_DANGER = list(CANONICAL_DANGER_TOOLS) — ليست مصدر حقيقة ثانيًا. أدوات spawn فقط إذا كانت على CANONICAL.
3.3 محوّلات الناقل
Section titled “3.3 محوّلات الناقل”TelegramBusAdapter / DiscordBusAdapter / SlackBusAdapter. مُفرد على مستوى العملية get_message_bus().
توصيل التطبيق (app.py): اجمع كل منصة مُعدَّة. واحدة ← ذلك المحوّل. اثنتان أو أكثر ← FanOutBusAdapter. لا شيء ← NullBusAdapter (خطر فاشل-مغلق).
request_approval الخاص بـ FanOut ثلاثي الحالات (Wave 6 H-12): يُسوّي True؛ وFalse صوت حتى expected_voters أو الموعد النهائي. يجب ألا يقتل رفضُ Discord موافقةَ Telegram. هذا ليس claim_gate الخاص بالويب (أول مطالبة 200 / الثانية 409).
يتخطّى pytest المحوّلات الحقيقية (_skip_real_adapters).
3.4 الاستدعاءات الراجعة
Section titled “3.4 الاستدعاءات الراجعة”يحلّ handle_callback() الخاص بكل محوّل زرّ المنصّة على الموافقة المشتركة. في Telegram: swarm_approve_<task_id> / swarm_reject_<task_id>؛ وفي Discord مكوّنات (components)؛ وفي Slack التفاعلات.
4. المسار C — نقاط حفظ خط المعالجة
Section titled “4. المسار C — نقاط حفظ خط المعالجة”راجع تنسيق السرب ← نقاط حفظ خط المعالجة.
- يُسجّل
CheckpointManager.handle_pipeline_checkpointأيضًا عبر_gate_register_pipeline. - رفض تلقائي عند انتهاء المهلة إذا كان
checkpoint_timeout > 0. - الموافقة / الرفض تسوّيان صف السجلّ. T-2: يجب أن تُنهي المهلة المهمة وتُنفِّذ
settle_gate. - يُعيد
restore_paused_tasks()تسليح المهل بعد إعادة التشغيل. - نقاط النهاية:
POST /api/swarm/tasks/{id}/approve//reject.
مقاطعات التوضيح / التأكيد الدلالية (طبقة الالتزام)
Section titled “مقاطعات التوضيح / التأكيد الدلالية (طبقة الالتزام)”ناقل HITL الموحَّد نفسه الذي يحمل موافقات الأدوات الخطيرة (البوابات A/B/C أعلاه) يحمل أيضًا نوعًا ثانيًا من المقاطعة: بطاقات توضيح/تأكيد دلالية تُنتجها طبقة الالتزام.
هذه ليست موافقات أدوات خطيرة — بل تُطلق عندما يكون قصد الوكيل غامضًا أو
حرجًا قبل تعديل دائم، لا لأن الأداة خطيرة. مثال: يقول المستخدم “ذكّرني
بالاجتماع” فيستدعي النموذج أداة الجدولة بتوقيت غامض. تُعيد بوابة الالتزام
(authorize_effect) قيمة clarify، ويُعلَّق الرسم البياني عبر interrupt()
بحمولة تحمل سؤالًا وقائمة خيارات (لكلٍّ منها slots_patch).
| نوع المقاطعة | متى تُطلَق | kind الحمولة |
|---|---|---|
| موافقة أداة خطيرة | الأداة على قائمة الخطر (البوابات A/B/C) | hitl_approval |
| توضيح دلالي | القصد غامض (مثلًا: وقت نسبي + حدث قريب) | semantic_clarify |
| تأكيد دلالي | فعل حرج يحتاج موافقة صريحة | semantic_confirm |
تُعرَض على كل منصّة — الويب (المحادثة + الشريط الجانبي)، وTelegram، وDiscord،
وSlack. تعرض كل بطاقة دلالية زرًا واحدًا لكل خيار؛ ويُعيَّن زرّا الموافقة/الرفض
الحاليان إلى أفضل خيار / إلغاء (build_resume_value في
commitment/resume.py). عند الاستئناف، يُطبَّق slots_patch الخاص بالخيار
المختار على وسائط الأداة ويُستكمل الدور؛ والإلغاء نهائي.
خريطة القرار الكاملة (allow / clarify / confirm / deny + إعادة الكتابة
عند السماح)، ومحلّلات الأفعال (التذكير، قائمة منع exec، المفاتيح المحمية في
الإعداد، قائمة سماح الصادر)، ورموز النطاق، وبوابة تأكيد الروح، والأوضاع،
ومفاتيح الإيقاف — موثَّقة في الدليل المخصَّص:
طبقة الالتزام (الحلّ قبل الفعل).
5. قوائم الأدوات الخطيرة
Section titled “5. قوائم الأدوات الخطيرة”يجب أن تبقى CANONICAL + YAML + الإعدادات مجموعة واحدة. و_EXTENDED_DANGER الخاص بالسرب نسخة من CANONICAL. وMCP قائم على الأنماط (غير معروف ← خطر). وTOOL_TIERS هي الأرضية لأي أداة مُسجَّلة.
5.1 المسار A (الرسم البياني) — kazma.yaml safety.hitl.require_approval_for
Section titled “5.1 المسار A (الرسم البياني) — kazma.yaml safety.hitl.require_approval_for”الافتراضي (kazma.yaml تحت safety.hitl.require_approval_for، ويجب أن يطابق CANONICAL_DANGER_TOOLS): يشمل file_write، وfile_apply_patch، وfile_delete، وshell_exec، وcode_exec، وpython_exec، وcomputer_use، ومُغيّرات git/GitHub، والخزنة، والمُثبّتات، وإرسال/حذف البريد، وrequest_path_access، وx_post، وx_delete_post، وx_schedule_post، وx_cancel_scheduled_post. مُختبَر التكافؤ.
HITL دائم (شروط استخدام X): تتطلّب ALWAYS_HITL_TOOLS (x_post، وx_delete_post، وx_schedule_post، وx_cancel_scheduled_post) موافقةً حتى عندما يتخطى YOLO أو الصلاحيات الدائمة أو تعطيل HITL الأدواتِ الخطيرةِ الأخرى. لا تعرض بطاقتها إلا موافقةً لمرة واحدة (Approve once / Deny؛ ولا “Approve for task” في تطبيقات المحادثة) وتسمّي الفعل العلني (“Publish to X — public, can’t be undone”، Post now). ويرفض مسار الموافقة إجابةَ tool أو yolo عليها برمز 409 one_time_only، وتبقى البطاقة معلّقة. ذلك مسار المحادثة/الوكيل. أما على الويب، فيعامل استوديو X (/x) و/api/scheduled/x نقرةَ المشغّل كالموافقة (يستدعيان publish_x_post / book_x_post / delete_x_post مباشرة — ولا يستخدمان أدوات المحادثة). الـ API الرسمي فقط — راجع ناشر X.
بوابة دائمة لكتابات git (2026-08): تتطلّب git commit وpush وmerge و
rebase وreset وcheckout -- وrestore وclean وrm وأشباهها بطاقةَ
موافقة على كل مسار تنفيذ — لا يستطيع YOLO الموافقة تلقائيًا على تعديلات
المستودع (سوء قراءة القصد يجب أن يكلّف حوارًا، لا commit أبدًا؛ حادثة
2026-08-27). أما git القرائي (status/log/diff) فمعفى. كذلك صارت نوافذ
YOLO افتراضيًا ساعة واحدة (كانت 4) — ويتجاوزها KAZMA_YOLO_TTL_SECONDS.
راجع سجلّ المهام.
تُزال النافذة المنتهية خلال 15 دقيقة سواء أُعيد فتح محادثتها أم لا، ويُعَدّ
علمٌ من قبل أن يكون للنوافذ وقت انتهاء منتهيًا: حتى 2026-09-28 كان يُعمَل
بمثل هذا العلم إلى الأبد، وقد كانت محادثة واحدة في التثبيت الحي قد تخطّت
الموافقات بموجبه منذ يوليو.
الاحتياطي في الكود إن لم يُضبط: DEFAULT_DANGER_TOOLS = ["file_write", "file_delete", "shell_exec", "vault_retrieve", "vault_delete"] (safety/hitl.py:41). تحمي أدوات الخزنة استرجاع/حذف الأسرار.
حارس التضييق: أدوات الخطر الكانونية جزء دائم من القائمة الفعّالة — الأرضية مُفعَّلة افتراضيًا منذ تدقيق 2026-09-16 F-5 — فلا تستطيع الإعدادات/YAML التضييق دونها. يُلغي
KAZMA_HITL_CANONICAL_FLOOR=0ذلك، مع تحذير، ثم يتكرر تحذير الانحراف كل 15 دقيقة يسمّي الأدوات المتروكة.
5.2 المسار B (ناقل السرب) — _EXTENDED_DANGER
Section titled “5.2 المسار B (ناقل السرب) — _EXTENDED_DANGER”_EXTENDED_DANGER = list(CANONICAL_DANGER_TOOLS) — نسخة مُجسَّدة لأن CANONICAL هي tuple. المحتويات نفسها. إضافة أداة خطيرة تعني CANONICAL وkazma.yaml (اختبارات التكافؤ تقارن المجموعات). أدوات spawn فقط إذا كانت على CANONICAL.
إضافة إلى _SENSITIVE_READS = ["sqlite_query", "file_search"] — مسموحة لكن مُسجَّلة.
5.3 MCP — classify_mcp_tool()
Section titled “5.3 MCP — classify_mcp_tool()”mcp/manager.py:71-88 — مطابقة ديناميكية لأنماط الأسماء (أدوات MCP تُكتشَف وقت التشغيل):
- خطر إذا وُجد أيٌّ من:
write, delete, remove, exec, run, shell, bash, command, kill, terminate, install, deploy, upload, download, fetch, request, post, put, patch. - آمنة إذا وُجد أيٌّ من:
read, list, search, get, info, status, check, describe, query, count, exists, help. - غير معروفة خلاف ذلك.
غير المعروف يُعدّ خطرًا افتراضيًا. يتطلّب
UnifiedToolExecutor.execute()موافقة للحالتين معًاdangerوunknown. لا تُضعِّف هذا أبدًا. الأدوات المحلية: ينتهيrequires_approval()عندTOOL_TIERS— الأداة المُسجَّلة غير المصنَّفة تبقى خلف البوابة (F-04). أضف مستوى (read/write/danger) عند تسجيل أداة.
6. التكامل التشفيري (ما وراء HITL)
Section titled “6. التكامل التشفيري (ما وراء HITL)”6.1 توقيع HMAC للمهارات (Hub)
Section titled “6.1 توقيع HMAC للمهارات (Hub)”موثَّق في المهارات وMCP والأدوات ← التوقيع التشفيري. الملخّص:
- يكتب
kazma hub signقيمتيchecksum(SHA-256) وsignature(HMAC-SHA256 فوق الـ checksum، بمفتاحKAZMA_SECRET) فيskill_manifest.yaml. - يتحقّق
SkillLoader._load_module_from_fileمن كليهما عبرhmac.compare_digest(بوقت ثابت) ويرفض تحميل المهارات المُعبَث بها/غير الموقَّعة عند اشتراط التوقيع.
6.2 لا تفويض موقَّعًا بين الوكلاء
Section titled “6.2 لا تفويض موقَّعًا بين الوكلاء”لا شيء في كاظمه يوقّع العمل المُسلَّم من وكيل إلى آخر أو يشفّره. حزمة تفويض
بين الوكلاء (توقيع Ed25519، واتفاقية مفاتيح X25519 + AES-256-GCM) لم توصَل
بالمنتج قط: بقيت في archive/ وحُذفت في 2026-07-28. العمل بين عمّال السرب
يوزّعه SwarmEngine (kazma_core/swarm/)؛ وما يحميه موجود في هذه الصفحة —
بوابة ناقل السرب، ورمز النطاق في طبقة الالتزام،
وقوائم الأدوات الخطرة — لا توقيع الرسائل.
وتذكر خارطة الطريق أن التفويض الموقَّع ليس في
الكود.
6.3 سرّ نقطة نهاية HITL
Section titled “6.3 سرّ نقطة نهاية HITL”نقطة النهاية POST /api/approve/{thread_id} محمية بجلسة / KAZMA_SECRET (secrets.compare_digest). يُحلِّل get_kazma_secret() البيئة ← KAZMA_AUTH_DISABLED ← تخطّي pytest ← security.secret في قاعدة البيانات ← توليد تلقائي. خارج localhost، اضبط KAZMA_SECRET دائمًا. KAZMA_AUTH_DISABLED لجهاز واحد: يرفضه حارس الإقلاع مع ربط بغير loopback أو خلف وكيل مُعلَن (KAZMA_TRUSTED_PROXIES: النفق على الجهاز نفسه يجعل ربط loopback علنيًا)، وما دام مضبوطًا يُجاب الطلب الذي جاء عبر وكيل بالرمز 503.
7. سلوكيات الفشل-المُغلق (الجرد)
Section titled “7. سلوكيات الفشل-المُغلق (الجرد)”| المكوّن | سلوك الفشل-المُغلق |
|---|---|
SafetyMiddleware.check_sync | يحجب الأدوات الخطيرة عند غياب ناقل حقيقي + allow_headless_danger=False. |
ToolRegistry.execute | أي استثناء في فحص السلامة ← “blocked — SafetyMiddleware unavailable”. |
classify_mcp_tool | unknown ← يتطلّب موافقة. |
SkillLoader | توقيع مُعبَث به/مفقود ← SkillLoadError، دون تحميل. |
| Hub write API | غياب KAZMA_SECRET ← رفض جميع عمليات الكتابة. |
| استلام التفويض | توقيع مفقود/غير صالح ← رفض. |
| نقطة نهاية موافقة HITL | موافقة بين مستخدمين ← 403؛ غياب KAZMA_SECRET ← راجع التحذير أدناه. |
⚠ تحذير الإنتاج: إذا كان
KAZMA_SECRETغير مضبوط، فقد يُعيدget_kazma_secret()سلسلة فارغة""وتصبح نقاط نهاية الموافقة غير مُصدَّقة. اضبطKAZMA_SECRETدائمًا لأي نشر غير localhost. (لا يربطkazma serveعلى0.0.0.0إلا عند ضبطKAZMA_SECRET— هذا عن قصد.)
8. ملفات إعداد الأمان
Section titled “8. ملفات إعداد الأمان”يُعلن kazma-security.yaml عن الوضعية عبر scanning، وdisclosure، وbug_bounty (معطَّل — لا برنامج مدفوع)، وhardening. لا يقرأ أي كود في كاظمه ذلك الملف (فُحص في 2026-09-27): إنه يوثّق برنامج الأمان للبشر، ولا شيء أدناه يعمل بسببه. يعرض قسم hardening فيه 8 فحوصات (secrets_in_logs، وinput_validation، وrbac_enforcement، وtls_required، وdependency_audit، وleast_privilege، وaudit_trail، وconfig_integrity). راجع الإعداد ← إعداد الأمان وSECURITY.md في الجذر. ويُعرِّف kazma-permissions.yaml قوائم السماح/المنع لأدوات MCP القائمة على الأقسام (أقسام ALMuhalab) مع قواعد عابرة للأقسام (require_explicit_approval، وmax_approval_duration_hours: 24، وaudit_all_access).
8.1 تقرير التحصين (security/hardening.py)
Section titled “8.1 تقرير التحصين (security/hardening.py)”SecurityHardeningRunner تقرير مُشغَّل عند الطلب، لا بوابة. يشغّله GET /api/security/hardening فوق التثبيتة (المجلد الذي يعمل منه كاظمه، لا مجلد العمل الحالي) بوصفه تشخيصًا للقراءة فقط، ويعيد النتائج. يعمل كل فحص في خيط عامل، فيبقى الخادم يجيب. ويستغرق التشغيل الكامل نحو 10 ثوانٍ، معظمها في الاستعلام من OSV. لا يعمل عند بدء التشغيل، ولا تستدعيه أي صفحة بعد. المفتاحان run_on_startup / fail_on_critical في kazma-security.yaml غير مقروءين.
يقيس كل فحص الخاصية التي يحمل اسمها، بالجواب نفسه الذي يستعمله باقي كاظمه:
| الفحص | ما يقرؤه | الخطورة |
|---|---|---|
check_no_hardcoded_secrets | ملفات المنتج في التثبيتة، كما يسردها مستودع git الخاص بها. تُستثنى الاختبارات والوثائق والمجلدات المولَّدة و.env. يحكم security/secret_scan.py على القيم: صيغ الجهات المُصدِرة (كتل المفاتيح الخاصة، وAWS، وGitHub، وSlack، وGoogle، وStripe، وOpenAI، وAnthropic، وTelegram، وJWT)، والقيم التي تبدو عشوائية مُسندة إلى أسماء بيانات اعتماد، وكلمات المرور داخل عناوين URL. لا تُحسب القيم البديلة والقوالب ومؤشرات الخزنة وأسماء متغيرات البيئة. تذكر النتائج الملف والسطر، لا القيمة أبدًا. | critical |
check_mcp_sandboxing | خوادم MCP التي تحتفظ بسرّ كما كُتب لا بمؤشر إلى الخزنة (mcp_servers_store.servers_with_plaintext_secrets)، وحارس مساحة العمل لكل مهمة (KAZMA_MCP_SCOPE_GUARD). | high |
check_rbac_enforcement | من يصل إلى الواجهة البرمجية: جواب حارس الإقلاع (عنوان الربط، والوكيل المُعلَن، وKAZMA_AUTH_DISABLED / KAZMA_DEV_WS_BYPASS / KAZMA_DEMO_MODE)، إضافةً إلى KAZMA_SECRET مضبوط يدويًا أقصر من 20 حرفًا. | high |
check_dependency_vulnerabilities | تنبيهات OSV للإصدارات المثبّتة فعلًا (8.2). فشل OSV يُفشل الفحص، ولا يُعرض أبدًا على أنه نظيف. | critical |
check_skill_manifest_validity | المهارات المدمجة، مفحوصة كما يحمّلها المُحمِّل: يُحلَّل ملف التعريف، وكل أداة يسمّيها موجودة. ومهارات الوكيل، مفحوصة كما يفحصها التفعيل: ملف SKILL.md صالح، وفحص السلامة الذي يطبّقه التفعيل (تفشل المهارة المعبوث بها؛ وتُعدّ المهارة غير الموقّعة). | medium |
check_encrypted_communications | هل تصل حركة المرور من الأجهزة الأخرى عبر TLS. ينجح الفحص إن لم يكن الوصول ممكنًا إلا محليًا. وإن كان كاظمه مكشوفًا (ربط بغير loopback، أو وكيل مُعلَن)، فيجب أن يكون KAZMA_PUBLIC_URL عنوانًا بـ https://. | high |
check_audit_logging | سجلّ الموافقات (hitl_gates.db): أنه مُفعَّل (KAZMA_GATE_REGISTRY) ومقروء. تذكر الرسالة عدد القرارات التي يحتفظ بها. | high |
check_permission_escalation | الاستدعاءات في شيفرة المنتج التي تشغّل صدفة (shell) أو تقيّم شيفرة: subprocess مع shell= صحيح أو مُقرَّر وقت التشغيل، وos.system، وos.popen، وsubprocess.getoutput، وcreate_subprocess_shell، وeval، وexec. تُحلّ الأسماء المستعارة للاستيراد. ويُطابَق كل استدعاء مع _REVIEWED_SITES، التي تسجّل سبب أمان الموضع. فيها اليوم مدخل واحد: خطافات الأدوات التي يكتبها المشغّل. | critical |
الفحص الذي لا يمكن تشغيله يُعرض فاشلًا مع سببه، وتعمل بقية الفحوص. حتى 2026-10-02 كانت أربعة فحوص تنجح لمجرد كلمة مفتاحية في أي مكان، وأربعة تفشل بنتائج غير صحيحة (ذاكرة حزم مؤقتة داخل التثبيتة، والحدود الدنيا للمتطلبات تُرسل إلى OSV، واسم ملف تعريف خاطئ). وأُزيلت fix_issues، التي كانت تكتب ملف .env داخل التثبيتة ولم يستدعها شيء.
8.2 مسح التبعيات (security/dependency_scanner.py)
Section titled “8.2 مسح التبعيات (security/dependency_scanner.py)”تقرأ audit_installed() التوزيعات المثبّتة في البيئة (بأسماء PEP 503، وبلا وسوم الإصدار المحلية). وتسأل واجهة OSV المجمّعة عن كل (name, version) بعينه، متتبّعةً رموز الصفحات، ثم تقرأ ملخّص كل تنبيه والإصدار الذي يصلحه. يُدرج OSV معظم تنبيهات PyPI تحت معرّفين، معرّف GHSA ومعرّف PYSEC، يسمّي كل منهما الآخر اسمًا مستعارًا، فيعدّ التقرير كل تنبيه مرة واحدة. وإذا تعذّر الوصول إلى OSV رُفع DependencyQueryError. ولا يُخزَّن شيء مؤقتًا.
بعض التنبيهات لا إصدار يصلحها، ولا يمكن بلوغها من خلال استعمال كاظمه للحزمة. تسردها REVIEWED_ADVISORIES، ومع كل منها السبب والشيفرة التي ستجعلها قابلة للبلوغ: أربعة تنبيهات لـchromadb تخص خادم Chroma عبر HTTP (يضمّن كاظمه Chroma داخل عمليته ولا يشغّل خادم Chroma)، وتنبيه واحد لـaccelerate في load_checkpoint_in_model (لا يستدعيها كاظمه). يسمّيها التقرير «مُراجَعة»، لا «نظيفة» أبدًا، ويفشل اختبار إن بدأت شيفرة المنتج تستخدم خادم Chroma أو تلك الدالة.
الحدود الدنيا حدودٌ أمنية. يرفع pyproject.toml الحد الأدنى لإصدار الحزمة إلى الإصدار الذي يصلح التنبيه، بما في ذلك حزم يعمل عليها كاظمه دون أن يستوردها بالاسم (urllib3 وanyio وpyasn1، ولكل إضافة aiohttp وoauthlib وtorch وtransformers وsetuptools وvirtualenv). يثبّت kazma update بالإضافة (uv pip install -e)، فالحد الأدنى هو ما يجعله يرقّي تثبيتةً تحمل إصدارًا مصابًا؛ أما ملف القفل وحده فلا يغيّر إلا التثبيتات الجديدة. والنشر عبر git pull لا يثبّت شيئًا، لذا يقارن الخادم عند الإقلاع الحزم المثبّتة بما يعلنه هذا الإصدار (kazma_core/install_requirements.py: ملف pyproject.toml الخاص بالنسخة، لأن البيانات الوصفية المثبّتة تتقادم مع كل سحب). وحين تكون التثبيتة متأخرة، يسجّل تحذيرًا (WARNING) يسمّي كل حزمة، ويطلق تنبيه التشغيل install.requirements_unmet. ويثبّت kazma update --reinstall -y الحدود الدنيا الناقصة؛ وفي تثبيت يشرف عليه الحارس يوقف كاظمه عبر الحارس متى لم تبقَ دورة محادثة جارية، ثم يشغّله من جديد بعدها (تحديث كاظمه ← حين يقول الخادم إن حزمه متأخرة). ويعرض فحص التبعيات في التقرير القائمة نفسها، ويعمل دون OSV.
يشغّل GET /api/security/deps الدالة scan_skill_manifests() على المهارات المثبّتة من المركز. ويذكر لكل مهارة:
- بيانات اعتماد مكتوبة في ملف التعريف (بالكاشف نفسه
secret_scan)؛ command:يعمل عبر صدفة مع-cأو/cأو-Command؛--privileged، أو شبكة المضيف، أوsudo، أوchmod 777، أو بتّات set-ID؛- تنبيهات OSV للإصدارات المثبّتة من متطلبات
requirements.txtالخاصة بالمهارة. ويُسمّى المتطلَّب غير المثبّت.
إذا فشل OSV يكون الجواب {"status": "error"}، لا قائمة فارغة أبدًا.
لا يُجدوَل أيٌّ من المسحين. قسم scanning في kazma-security.yaml (فاصل 24 ساعة، وauto_create_issues) غير مقروء. ما يعمل وفق جدول هو جدول GitHub: طلبات pull الأسبوعية من Dependabot لتحديث ملف القفل uv (.github/dependabot.yml؛ وحتى 2026-10-02 كان يراقب منظومة pip، التي لم تلمس uv.lock قط)، وبوابة bandit العالية (HIGH) في كل تشغيل CI. ويفشل أمر uv export --locked في CI وخطوة SBOM في الإصدار حين لا يعود uv.lock يطابق pyproject.toml.
8.3 تدفّق الإفصاح (security/disclosure.py)
Section titled “8.3 تدفّق الإفصاح (security/disclosure.py)”يُفرِض SQLite kazma-data/disclosure.db سلسلة الانتقال submitted → acknowledged → investigating → confirmed → patched → closed. يُولِّد publish_advisory() مُعرِّفًا داخليًا KAZMA-ADV-YYYY-… (ليس CVE من MITRE) مع قالب markdown، من حالتَي patched/closed فقط. يُوقِّع encrypt_report() حمولة JSON بتوقيع HMAC-SHA256 بمفتاح KAZMA_DISCLOSURE_KEY.
kazma-security.yaml: نافذة الاستجابة 48 ساعة، والتقييم 7 أيام، وsecurity_txt_url (ملف اتصال RFC 9116 — ليس مفتاح PGP)، والقنوات البريد + الإبلاغ الخاص على GitHub. bug_bounty.enabled: false (لا مكافأة مدفوعة). السياسة الكانونية: SECURITY.md في الجذر والإبلاغ عن الثغرات.
ما يُفرض الأمان وقت التشغيل موجود في الكود، لا في
kazma-security.yaml: بوابات الموافقة (§7 من AGENTS.md)، وطبقة الالتزام، والخزنة، وفحوص SSRF/CSRF والسياج — لكلٍّ منها بوابته فيtests/. ملف YAML إعلان.
9. توصيات التحصين
Section titled “9. توصيات التحصين”- اضبط
KAZMA_SECRETدائمًا للنشر غير المحلي. ولِّده عبرopenssl rand -hex 32. - شغّل خوادم MCP من نوع stdio داخل بيئة معزولة. ناقل stdio بلا مصادقة؛ يحصل الخادم على الأساسيات المسموح بها مع
envالخاص به (تدقيق H-4)، ولا يحصل أبدًا على أسرار كاظمه، ويعمل بصلاحيات عملية كاظمه. - فضِّل MCP من نوع SSE مع مصادقة bearer لأي خادم MCP بعيد.
- وقّع جميع المهارات (
kazma hub sign) وأبقِKAZMA_SECRETمتّسقًا عبر التحميل — وإلا فشل التحقّق من التوقيع. - أبقِ مسارات تنفيذ HITL الثلاثة + السجلّ مُفعَّلة. لا تمرّر
hitl_config=Noneفي رسم بياني إنتاجي قابل للاستئناف. ولا تُنشئ بوابة ويب ثانية منexecute(). - لا تضبط
allow_headless_danger=Trueفي الإنتاج. إنه مخرج الاختبار/التطوير. - اعمل بحساب المستخدم غير الجذري
kazmaفي Docker (يقوم Dockerfile بذلك أصلًا). - اربط على
127.0.0.1ما لم يكن لديك وكيل عكسي +KAZMA_SECRETجاهزان. - تعدد المشغّلين: اضبط قوائم سماح المنصات +
KAZMA_GATEWAY_STRICT_ALLOWLIST=1(2026-08-19) — افتراضيًا تعمل محوّلات Telegram/Discord/Slack بالسماح-للجميع توافقًا مع التثبيتات أحادية المشغّل؛ والوضع الصارم يفشل مغلقًا عند قائمة سماح فارغة. - اترك
KAZMA_HITL_CANONICAL_FLOORغير مضبوط — الأرضية مُفعَّلة افتراضيًا، والقيمة0تسمح بتضييق قائمة موافقات أدوات الخطر دون المجموعة الكانونية. - اضبط
KAZMA_TRUSTED_PROXIESعندما تكون خلف nginx/Caddy/Docker. عنوان النظير127.0.0.1ليس اعتمادًا. - لا تثبّت الكشط عبر
proxy=. تستخدم القفزات المباشرةPinHostAsyncTransport؛ وإحباط النظير الخاص يعمل دائمًا. - إذا وصلت خوادم MCP، فوافق على كل استدعاء أو سمِّ الأداة في
KAZMA_MCP_SAFE_ALLOWLIST. الخادم هو من يقدّم اسم الأداة. ما تزالget_fileوread_envوget_ssh_keyوlist_env_varsتُصنَّفsafe، وهذه التسمية لا تتخطى البوابة.read_envهي التي يجب التفكير فيها: غابتenvعمدًا عن قائمة سماحshell_execتحديدًا كي لا تتحوّل موافقة واحدة إلى تفريغ للاعتمادات.KAZMA_PRODUCTION=1لا يسمح بهذه الأسماء.
الرفض الافتراضي، وCSRF، وSSRF (2026-08-29 / Wave 8)
Section titled “الرفض الافتراضي، وCSRF، وSSRF (2026-08-29 / Wave 8)”هذه تجلس بجانب HITL، لا داخله.
| القاعدة | المكان |
|---|---|
| الأداة غير المصنَّفة تبقى خلف البوابة | requires_approval() ← TOOL_TIERS (الرفض يفوز) |
| السماح لثنائي ليس سماحًا لما يشغّله | _EXEC_CAPABLE_ARGS الخاص بـ shell_exec (find -exec، وgit -c، …) |
| إخفاء الأسرار تعاودي | settings.mask_deep() — القوائم وسلاسل JSON أيضًا |
| كلمة المرور داخل URL سرّ | تُخفى بالقيمة عند كل مخرج (security/url_credentials.py)، مهما كان اسم الإعداد؛ وعناوين URL للذاكرة الخلفية التي تحوي كلمة مرور تذهب إلى الخزنة |
| CSRF | csrf.py: طلب غير GET على /api/* مع Origin/Referer غير متطابق ← 403. استخدم request.url.hostname (لا .host في Starlette) |
/health/details حسّاس | L-1؛ وتبقى /health/live و/health/ready عامّتين |
| تثبيت IP لـ SSRF | يُعيد validate_url عناوين IP عامة؛ وPinHostAsyncTransport عند غياب الوكيل؛ وassert_peer_public بعد كل قفزة |
| الأخطاء | safe_error / validation_error في API؛ لا تفاصيل داخلية في هياكل 4xx/5xx |
| مخرجات الأدوات المُسيَّجة | الصفحات المجلوبة / البحث / موارد MCP تمرّ عبر fence_untrusted — راجع القسم 10 |
CI: tests/test_audit_2026_08_29_regressions.py، وtests/test_audit_wave8.py، وtest_every_registered_tool_has_a_tier.
10. سياج التوجيه — ما يوقفه، مُقاسًا
Section titled “10. سياج التوجيه — ما يوقفه، مُقاسًا”النص غير الموثوق — صفحات الويب المجلوبة، ومقتطفات البحث، ونتائج أدوات MCP
وهياكل الموارد — يُغلَّف قبل أن يراه النموذج. نقطة الدخول الإنتاجية هي
fence_untrusted(content, *, source, is_error=False) في
kazma_core/safety/prompt_fence.py؛ وformat_untrusted_block هي الدالة
الداخلية التي يستدعيها.
الثقة تأتي من المستدعي، لا من المحتوى أبدًا. is_error=True هي طريقة
المستدعي لقول “هذه السلسلة رسالة فشلي أنا، لا نص طرف ثالث”، وهي الطريقة
الوحيدة لتخطّي السياج. هذا ليس تفضيلًا أسلوبيًا: فقد حلّ العلم محل فحص كان
يستنشق content.startswith("Error:")، ولأن كل مستدعي يمرّر نصًا يتحكم به
المهاجم، كان مهاجم يبدأ حمولته بتلك الأحرف الست يوصلها إلى النموذج بلا
سياج. قرار الثقة المُستخرَج من المحتوى هو قرار ثقة يكتبه المهاجم.
وفشل التسييج نفسه يفشل مغلقًا — إذا رمى السياج استثناءً، يحصل المستدعي على نص بديل يسمّي المصدر وعدد الأحرف المحجوبة، لا النص الخام.
نص المستندات تسيّجه منصة المستندات نفسها، باستخدام
format_untrusted_block (بالمصادر document وdocument_attachment و
document_knowledge)؛ انظر أمان المستندات.
ما يُقاس أنه يفعله
Section titled “ما يُقاس أنه يفعله”| نجاح الهجوم | اتُّخذ إجراء وفق الحمولة | |
|---|---|---|
| بلا دفاع | 18.1% | 24.1% |
| تسليط الضوء (محدِّد من 4 أحرف، من الأدبيات) | 11.6% | 18.6% |
| سياج كاظمه | 10.4% | 14.8% |
996 تشغيلًا لكل شرط على AgentDojo، معيار عام لم تكتبه كاظمه، وكل شرط قيس أربع مرات. يتفوّق السياج على انعدام الدفاع بفارق حاسم (p < 0.001) ولا يمكن تمييزه عن محدِّد من أربعة أحرف (p = 0.39).
كلا النصفين من ذلك مهم. تسييج مخرجات الأدوات غير الموثوقة يعمل. وهو أيضًا ليس حيث تكمن ميزة كاظمه، والصفحة أدناه تقول ذلك بدل أن تتركك تكتشفه بنفسك.
قبل أن تعتمد عليه
Section titled “قبل أن تعتمد عليه”- حقن التوجيه: الأرقام — القياس الكامل، والحمولات التي ما زالت تصيب، وإعادة الإنتاج التي يمكنك تشغيلها مجانًا بلا مفتاح API.
- نموذج التهديد — ما يوقفه كل حدّ، وبصراحة، ما لا يوقفه. الموافقة رضا، لا احتواء.
- الفجوات المعروفة
— نقاط ضعف مفتوحة، مؤرَّخة. بينها واحدة تمسّ افتراضات هذه الصفحة
نفسها: اسم الأداة الذي يقدّمه خادم MCP نفسه ما يزال يصنّف
read_envآمنة، وتلك التسمية ليست موافقة. يعمل الاستدعاء عندما توافق عليه، أو عندما يكون ذلك الاسم علىKAZMA_MCP_SAFE_ALLOWLIST. وضع الإنتاج لا يغلقها.
يقلّل السياج نجاح الهجوم. لا يلغيه، ولن يكون أي رقم صادق هنا 0% أبدًا.
ملاحظات تدقيق التوثيق
Section titled “ملاحظات تدقيق التوثيق”- اسم الصنف: سلامة السرب هي
SafetyMiddleware، وليستSafetyGate/SafetyChecker. - نقطة نهاية الموافقة:
approve_toolفيroutes_direct/misc.py، وليست فيapp.py. - لا تثبّت أرقام الأسطر.
tool_worker_nodeهوgraph_tool_worker.py؛ وSSE SoT هي إعادة تجميع app.py، لاget_streaming_graph()(ذلك المسار بلا checkpointer معauto_deny). - FanOut، لا Telegram فقط. منصات متعددة ←
FanOutBusAdapterثلاثي الحالات. _EXTENDED_DANGERهي CANONICAL، لا قائمة خاصة أطول. ويبقىclassify_mcp_toolالخاص بـ MCP قائمًا على الأنماط (غير معروف ← خطر).- “مستويات الثقة” غير موجودة كميزة منتج — راية الـHub المنطقية
certified، والإعدادtrust: trustedلخادم MCP الذي يتخطى بطاقة الموافقة لأدواته (ويُرفض في الإنتاج ما لم يكنKAZMA_MCP_TRUSTED_IN_PROD=1). - MCP من نوع stdio بلا مصادقة. اعزل وفق ذلك.
- تدقيق الربط:
AUDIT_DEEP_2026-09-01_EXEC.md.

