الجواب المختصر: إذا كان litellm==1.107.0 أو صورة LiteLLM على Docker جرى سحبها في 21 أكتوبر 2026 قد عملت يومًا على أحد أجهزتك، فاعتبر ذلك الجهاز مخترقًا. أوقف أولًا المُحمِّل الخفي (Loader)، ثم أعد بناء الجهاز من الصفر على الإصدار 1.106.2، وبدّل كل سر (Secret) كان الجهاز قادرًا على الوصول إليه، وامنع الاتصال بالنطاق litellm.dev. لا يوجد CVE لهذه الحادثة، لذلك قد لا يحذّرك فاحص الاعتماديات (Dependency Scanner) منها.
شاهد الفيديو:
https://youtube.com/shorts/0KsLVTXIW2gأستدعي واجهات برمجة التطبيقات (APIs) الخاصة بنماذج اللغة الكبيرة (LLM) من مشاريعي في Next.js وLaravel، وغالبًا عبر بوابة (Gateway) مثل LiteLLM، لذلك مسّتني هذه الحادثة مباشرة. سأشرح فيما يلي ما حدث وما غيّرته في عملي.
ماذا حدث
LiteLLM بوابة مفتوحة المصدر وشائعة. توفر واجهة واحدة بأسلوب OpenAI أمام OpenAI وAnthropic وGemini وBedrock وغيرها، إضافة إلى مفاتيح افتراضية وميزانيات وتسجيل للأحداث. في 21 أكتوبر 2026 نُشر الإصدار 1.107.0 وفيه برمجية خبيثة:
- PyPI: جميع حزم wheel السبع للإصدار
litellm==1.107.0، وكانت متاحة من 11:39 إلى نحو 13:23 بالتوقيت العالمي (UTC). - Docker: الوسم
v1.107.0والوسوم المتحركةlatestوmain-latestوmain-stableعلى Docker Hub وGHCR (litellmوlitellm-databaseوlitellm-non_root)، من 11:46 UTC حتى نحو 14:20 UTC على Docker Hub. - وسم المصدر
v1.107.0على GitHub سليم. السم كان في الحزم والصور المبنية فقط.
قد تبدو بضع ساعات مدة قصيرة، لكن أي جهاز نفّذ pip install litellm دون تثبيت للإصدار، أو سحب :latest، خلال هذه النافذة حصل على النسخة الخبيثة.
كيف اختُطف مسار الإصدار
هذا الجزء يجب أن يقرأه كل مطوّر، لأنه يبدأ من رموز مميزة (Tokens) في السجلات (Logs). بحسب التحليل اللاحق للحادثة (Post-mortem) الذي نشرته LiteLLM، وهو ما يزال قيد التحقيق:
- دخل المهاجم إلى نسخة LiteLLM داخلية مكشوفة عبر حساب مستخدم غير متوقع.
- كانت هذه النسخة تسجّل أجسام الاستجابات، فاحتوت السجلات على رموز OAuth الخاصة بـ GitHub CLI لثلاثة مطورين.
- كان أحد الرموز يخص مالكًا لمنظمة على GitHub. استخدمه المهاجم لتجاوز حماية الفروع (Branch Protection)، وجعل مسار الإصدار الخاص يشير إلى مستودع مشابه في الاسم هو
Berri-AI/litellm(لاحظ الشرطة). - بعد ذلك قام المسار الرسمي ببناء الحزم الخبيثة وتوقيعها ونشرها. ومرّ رمز مطوّر ثانٍ من بوابة الموافقة.
- استُخدم رمز ثالث لحذف سجلات تشغيل المسار.
لا ثغرة غير معروفة (Zero-day) في شيفرتك، ولا اسم حزمة مزيف بخطأ إملائي. الاسم موثوق، والمسار موثوق، والتوقيع حقيقي، وكل ذلك لأن أسرارًا انتهى بها المطاف في مكان لا يجب أن تكون فيه.
ماذا تفعل البرمجية الخبيثة
تُوضع ثلاثة ملفات في site-packages:
| الملف | ماذا يفعل |
|---|---|
cook.pth |
سطر واحد: import cook. تشغّل Python ملفات .pth عند كل بدء لمفسّر اللغة، فلا تحتاج حتى إلى استيراد LiteLLM. حتى pip يشغّله. |
cook.py |
أداة السرقة. تجمع 16 وحدة بيانات الاعتماد (Credentials)، وتشفّرها، وترسلها بطلب POST إلى http://www.litellm.dev/healthcheck. |
sitecustomize.py |
عملية خلفية منفصلة (Daemon) تتحقق كل ساعة من وجود شيفرة Python جديدة لتنزيلها وتنفيذها بـ exec(). |
ما تستهدفه:
- مفاتيح AWS من الملفات ومن بيانات وصفية للنسخة (Instance) أو ECS، وتختبرها عبر AWS STS قبل الإرسال. وتستهدف أيضًا بيانات اعتماد Azure وGoogle Cloud وKubernetes.
- المفاتيح الخاصة لـ SSH وGPG وTLS، وملفات
.envو.git-credentialsو.npmrcو.pypirc. - متغيرات البيئة (Environment Variables) لكل عملية يمكنها قراءتها، فتتسرب أيضًا الأسرار الممرَّرة إلى تطبيقات أخرى على الجهاز نفسه.
- إذا كان
DATABASE_URLمعرّفًا: قاعدة بيانات وكيل LiteLLM، أي كل مفتاح لمزوّد خدمة حفظته في البوابة. - كلمات مرور المتصفحات وملفات تعريف الارتباط (Cookies)، وبيانات اعتماد أدوات البرمجة بالذكاء الاصطناعي.
ملاحظة على العنوان الشائع «أمر pip واحد سرق مفاتيح AWS»: البرمجية تستهدف مفاتيح AWS وتتحقق منها بوضوح، لكن حتى اليوم لا يوجد تقرير يسمّي ضحية استُخدمت مفاتيحها فعلًا. ومع ذلك تنصح LiteLLM بأن تفترض نجاح تسريب البيانات على أي جهاز متضرر يتصل بالإنترنت.
هل أنا متأثر؟ فحوص سريعة
# 1. Pinned or resolved to the bad version?
grep -rn "litellm" requirements*.txt poetry.lock uv.lock Pipfile.lock 2>/dev/null
# 2. Images you pulled or run
docker images --digests | grep -i litellm
# 3. Payload files in any environment (use find, not Python)
find / -path "*site-packages*" \( -name "cook.pth" -o -name "cook.py" \) 2>/dev/null
ls -la /tmp/remote_code_loader.lock /tmp/.pc_once_72129118c59f5636c0bb 2>/dev/null
ابحث أيضًا في سجلات DNS وسجلات الاتصالات الصادرة (Egress) عن litellm.dev، وفي AWS CloudTrail عن استدعاءات GetCallerIdentity القادمة من أدوار نسخك (Instance Roles) في وقت التثبيت تقريبًا.
الإصلاح بالترتيب
- أوقف المُحمِّل أولًا. ابحث عن العملية التي تمسك الملف
/tmp/remote_code_loader.lockوأوقفها. لا تشغّلpipفي البيئة المصابة قبل ذلك. - احذف الملفات الخبيثة (
cook.pthوcook.pyوsitecustomize.pyوملفات__pycache__الخاصة بها)، ثم أعد بناء البيئة الافتراضية (Virtualenv) أو الصورة من الصفر علىlitellm==1.106.2. ثبّت الصورة باستخدام البصمة (Digest). - امسح ذاكرات التخزين المؤقت (Caches): مرايا PyPI الداخلية، وسجلات الصور الوسيطة (Pull-through Registries)، وذاكرات CI المؤقتة.
- بدّل كل شيء كان الجهاز قادرًا على الوصول إليه: مفاتيح السحابة وجلسات الأدوار، وكل مفتاح مزوّد في قاعدة بيانات LiteLLM، والمفتاح الرئيسي، والمفاتيح الافتراضية، وكلمة مرور قاعدة البيانات، ومفاتيح SSH، ورموز Git والسجلات (Registries)، وأسرار CI.
- امنع
litellm.devعلى مستوى DNS والاتصالات الصادرة.
الدرس لتطبيقات Next.js وLaravel
معظمنا لا يشغّل Python داخل تطبيقات الويب. لكن إذا كان معالج المسار (Route Handler) في Next.js أو خدمة Laravel ترسل الأوامر النصية (Prompts) إلى بوابة، فهذه البوابة هي الجهاز الوحيد الذي يحتفظ بـكل مفاتيح الذكاء الاصطناعي لديك. إذا اختُرقت مرة واحدة تسربت مفاتيح جميع المزوّدين.
1. لا تسجّل الرموز المميزة ولا أجسام الطلبات أبدًا
بدأ الهجوم كله من رموز مميزة في السجلات. افحص الأماكن المعتادة:
// Laravel: don't do this
Log::info('LLM call', ['headers' => $request->headers->all(), 'body' => $response->body()]);
// Do this: log what you need, never secrets
Log::info('LLM call', ['model' => $model, 'status' => $response->status(), 'ms' => $ms]);
في Laravel، أخفِ أيضًا ترويسة authorization في Telescope (Telescope::hideRequestHeaders) ونظّفها في أداة تتبع الأخطاء لديك. وفي Next.js لا تستخدم console.log(req.headers) أبدًا داخل معالج المسار، لأن هذه السجلات تُحفظ في معظم الاستضافات ويمكن البحث فيها.
2. ثبّت الإصدارات وبصمات الصور
استخدام litellm>=1.100 أو image: litellm:latest هو بالضبط الطريق الذي وصلت به هذه النسخة إلى الناس. ثبّت الإصدارات الدقيقة في ملفات القفل (Lock Files)، وثبّت الحاويات بالبصمة:
image: ghcr.io/berriai/litellm@sha256:<digest-of-1.106.2>
3. أعطِ كل تطبيق مفتاحه الصغير الخاص
استخدم المفاتيح الافتراضية (Virtual Keys) في البوابة لكل تطبيق، مع ميزانيات وحدود للطلبات، وأبعد مفاتيح المزوّدين الحقيقية عن خوادم تطبيقك. إذا تسرّب مفتاح واحد، فأنت تبدّل مفتاحًا واحدًا فقط.
4. لا تكشف البوابة
كان مدخل المهاجم نسخة داخلية مكشوفة. ضع واجهة الإدارة وواجهة API خلف شبكة افتراضية خاصة (VPN) أو شبكة خاصة، واسمح لخوادم تطبيقك فقط بالوصول إليها.
قائمة التحقق
- بحثتُ في ملفات القفل والصور عن
litellm 1.107.0وعن الوسوم المتحركة التي سُحبت في 21 أكتوبر - أوقفتُ المُحمِّل، وأعدتُ البناء من الصفر على 1.106.2، ومسحتُ ذاكرات التخزين المؤقت
- بدّلتُ أسرار السحابة ومزوّدي LLM والبوابة وقاعدة البيانات وSSH وGit
- منعتُ
litellm.dev - أزلتُ الرموز المميزة وأجسام الطلبات من السجلات (Laravel وNext.js وأداة تتبع الأخطاء)
- ثبّتُّ الإصدارات وبصمات الصور
شاهد الفيديو: [VIDEO LINK HERE]
المصادر
- منشور LiteLLM حول الحادثة (21 أكتوبر 2026): https://docs.litellm.ai/blog/security-incident-oct-21-2026
- تحليل StepSecurity: https://www.stepsecurity.io/blog/litellm-1-107-0-compromised-pypi-backdoored-wheels-credential-stealer
- تحليل Socket: https://socket.dev/blog/litellm-compromise
- Datadog Security Labs: https://securitylabs.datadoghq.com/articles/litellm-compromised-pypi-docker/
الأسئلة الشائعة
هل يوجد CVE لاختراق LiteLLM 1.107.0؟
لا. هذا اختراق في سلسلة التوريد البرمجية (Supply Chain) وليس خطأً في الشيفرة، لذلك لم يُخصَّص له CVE ولا GHSA. وقد لا تنبّه الفاحصات التي تعتمد على قواعد بيانات CVE إليه.
ما إصدار LiteLLM الآمن؟
توصي LiteLLM بتثبيت litellm==1.106.2 أو أي إصدار نُشر قبل 21 أكتوبر 2026. وقد أُزيل 1.107.0 من PyPI.
أستخدم صورة LiteLLM على Docker فقط. هل أنا متأثر؟
نعم، إذا سحبتَ v1.107.0 أو latest أو main-latest أو main-stable بين نحو 11:46 و14:20 UTC في 21 أكتوبر. افحص بصمات صور الحاويات التي تعمل لديك.
تطبيقي مبني بـ Laravel أو Next.js وليس Python. هل يهمني الأمر؟
إذا كان تطبيقك يتصل ببوابة LiteLLM، فإن جهاز البوابة كان يحتفظ بمفاتيح مزوّديك. بدّلها إذا كانت البوابة تشغّل النسخة الخبيثة، وطبّق دروس التسجيل وتثبيت الإصدارات المذكورة أعلاه.
هذا المقال ترجمة عربية للمقال الأصلي باللغة الإنجليزية للكاتب عبد المهيمن شموط على mouhimen.dev.
