
إصلاح جاهز للتطبيق مباشرة لثغرة حقن الأوامر غير المصحَّحة في MCP STDIO (عائلة CVE-2026-30623)
إصلاح جاهز (drop-in) لثغرة حقن الأوامر غير المُعالَجة في MCP STDIO (عائلة CVE-2026-30623، التي كشفت عنها OX Security في أبريل 2026 باعتبارها "بتصميم" -- لن يصدر أي تصحيح لـ SDK). استورد سطرًا واحدًا، وسيتم التحقق من الأمر/الوسائط/البيئة لكل خادم stdio MCP يُطلقه تطبيق Python الخاص بك قبل أن يُطلق نظام التشغيل أي عملية.
إذا كنت جديدًا هنا، اقرأ النطاق أولاً، ثم التثبيت والبدء سيحميانك في أقل من دقيقتين.
قبل الإصدار 1.0، قيد التطوير النشط.
check/launch/rules) مُنفَّذة
ومغطاة بمجموعة اختبارات آلية تعمل ضد الملفات التنفيذية الحقيقية المثبتة على
جهاز الاختبار (python, node, npx) -- وليس محاكاة (mocks) -- بما في ذلك
مصافحة MCP حقيقية من البداية إلى النهاية عبر كائن خادم مُطلق فعليًا (fixture)،
واختبار حقيقي على مستوى العمليات الفرعية (subprocess) لـ launch.ضمن النطاق: التحقق من إطلاق خادم stdio MCP (الأمر + الوسائط + البيئة) قبل وصوله إلى طبقة استدعاء العمليات في نظام التشغيل، تحديدًا لإغلاق مسار حقن الأوامر/الوسائط الموصوف في SECURITY.md.
خارج النطاق صراحةً: فحص الأدوات المُعلَنة للخادم بحثًا عن قدرات خطيرة (تلك مشكلة مختلفة -- انظر AgentGuard)، وعزل العملية المُطلقة (sandboxing)، ونواقل MCP غير stdio (SSE/HTTP).
git clone <this-repo>
cd mcpshield
pip install -e . # core CLI: click + rich only
pip install -e ".[mcp]" # if you also want the Python autopatch (needs the `mcp` SDK)
تحقق من نجاح التثبيت:
mcpshield --version
mcpshield --help
إذا كان تطبيقك مكتوبًا بلغة Python ويبني StdioServerParameters /
يستدعي mcp.client.stdio.stdio_client بنفسه، أضف استيرادًا واحدًا في أعلى
نقطة الدخول (entrypoint) الخاصة بك -- قبل أن يستورد أي شيء آخر mcp.client.stdio:
import mcpshield.autopatch # side-effect import; must come first
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
# ... use stdio_client exactly as before -- it's now validated
الإطلاق غير الآمن الآن يرفع mcpshield.core.errors.UnsafeConfigurationError
(فئة فرعية من ValueError) بدلًا من إطلاق أي عملية.
دقّق ملف إعداد من نوع mcpServers دون تشغيل أي شيء:
mcpshield check claude_desktop_config.json
+---------------------------------------------------------------+
| Server | Status | Command | Detail |
|------------------+---------+---------+------------------------|
| filesystem | OK | npx | - |
| evil-server | BLOCKED | npx | Argument '...' contains|
| | | | shell metacharacter |
+---------------------------------------------------------------+
1 ok, 0 warned, 1 blocked
يخرج برمز خروج غير صفري إذا كان أي عنصر BLOCKED (أضف --strict للفشل أيضًا
عند WARN) -- ضعه مباشرة في CI.
لعميل MCP (Node، Java، Rust، ...) لا يمكنه استخدام التصحيح التلقائي الخاص
بـ Python، وجّه إعداده إلى mcpshield بدلًا من الأمر الحقيقي:
{
"command": "mcpshield",
"args": ["launch", "--", "npx", "-y", "some-mcp-server"]
}
launch يتحقق، ثم ينفّذ الأمر الحقيقي مع نفس stdio الذي يتوقعه عميل MCP لديك
(تمرير شفاف) -- أو يرفض برسالة خطأ واضحة إذا كان الإطلاق غير آمن.
| الفحص | ملف تنفيذي أصلي (مثل python.exe) | قابل للتفسير عبر الصدفة (سكربت .cmd/.bat/shebang) |
|---|---|---|
محارف الصدفة (&, |, ;, backtick، $(...), ...) في وسيط | مسموح | محظور |
| بايت NUL / سطر جديد في وسيط | محظور | محظور |
يُحل الأمر عبر اجتياز مسار نسبي (..) | محظور | محظور |
| لا يُحل الأمر إلى ملف حقيقي | محظور | محظور |
LD_PRELOAD / NODE_OPTIONS / إلخ في البيئة | مُزال (تحذير) | مُزال (تحذير) |
PYTHONPATH في البيئة | مُشار إليه (تحذير)، دون إزالة | مُشار إليه (تحذير)، دون إزالة |
الملفات التنفيذية الأصلية تحصل على فحوص وسائط أكثر مرونة لأنها تنفّذ مباشرةً
عبر exec -- لا توجد صدفة لإعادة تفسير قائمة الوسائط. الأوامر القابلة للتفسير
عبر الصدفة (الأكثر شيوعًا npx.cmd/npx.bat على ويندوز) تحصل على فحوص صارمة
لأنها الآلية نفسها التي تستغلها ثغرة CVE الكامنة.
كلاهما اختيارات مقصودة، تُفعَّل قيمةً بقيمة (per-value) -- وليست أبدًا علمًا شاملاً "تعطيل الفحوص":
allow_raw_args=["--some-value-with-a-pipe"] (مكتبة) يعفي القيم المحددة
للوسائط التي راجعتها وتثق بها.allow_env=["SOME_VAR"] يسمح لمتغير بيئة يُزال عادةً بالمرور دون تعديل.| الأمر | الوظيفة |
|---|---|
mcpshield check <config> [--format table|json] [--strict] | تدقيق ثابت لإعداد mcpServers. لا ينفّذ أي شيء أبدًا. خروج غير صفري عند أي BLOCKED (وأيضًا WARN مع --strict). |
mcpshield launch -- <command> [args...] | يتحقق، ثم ينفّذ الأمر الحقيقي مع تمرير stdio. |
mcpshield rules list | يعرض قائمة حظر محارف الصدفة النشطة، وقوائم متغيرات البيئة، والملفات التنفيذية المعروفة والآمنة للإطلاق. |
git clone.mcp.client.stdio.stdio_client كما يُبحث عنه
في وقت التصحيح. أي كود يحمل مرجعه الخاص بالفعل (عبر
from mcp.client.stdio import stdio_client المنفَّذ قبل
import mcpshield.autopatch) سيتجاوز هذا التصحيح -- استورد mcpshield.autopatch
أولاً، دائمًا.check يحل الأوامر باستخدام الجهاز الذي يعمل عليه. الإعداد الذي قد يُحل
بشكل مختلف على الجهاز الذي يُنشر عليه فعليًا (PATH مختلف، أدوات مثبتة مختلفة)
قد يُبلغ بنتائج مختلفة هناك.mcpshield/
autopatch.py # one-line-import fix for Python MCP hosts
core/
validate.py # the validation engine (command/args/env checks)
rules.py # blocklist/allowlist data
errors.py # UnsafeConfigurationError
cli/
main.py
commands/ (check.py, launch.py, rules.py)
tests/
fixtures/ # real benign MCP server + sample/malicious configs
pip install -e ".[dev,mcp]"
pytest
تتحقق مجموعة الاختبارات من الملفات التنفيذية الحقيقية python/node/npx
المثبتة على الجهاز الذي تعمل عليه (تُحل بنفس الطريقة التي يحلها بها المحرك
نفسه)، وتتضمن مصافحة MCP حقيقية من البداية إلى النهاية عبر كائن خادم مُطلق
فعليًا (fixture) -- وليس محاكاة (mocks).