لكل اختراق في سلسلة التوريد لحظة تنتقل فيها الثقة بين الأيدي بهدوء. حدثت لحظتنا في نظام لا يكاد أي فريق ينظر إليه: الرابط بين مستودع على GitHub وحزمة على npm.
أطلق باحثو Bloom Security على الثغرة اسم SlugFest، والاستعارة التي استخدمها الباحث الرئيسي غولان مايرز هي التي بقيت: الأمر يشبه قفلاً يفحص العنوان على الباب بدلاً من مالك المنزل. وعندما ينتقل المالك، يحصل من ينتقل مكانه على المفتاح.
وهنا الجزء غير المريح: لم يكن على أحد أن يسرق أي بيانات اعتماد. الشرط الوحيد كان إعادة تسمية المستودع.
ما كان يُفترض أن يحله النشر الموثوق في npm
في يوليو 2025 أطلقت npm ميزة النشر الموثوق (trusted publishing)، وكانت الفكرة جيدة حقاً. فبدلاً من تخزين رموز npm طويلة الأمد على خادم البناء (وتسريبها عبر السجلات والذاكرات المؤقتة ومنافذ CI المخترقة)، يطلب سير عمل GitHub Actions رمز OpenID Connect قصير الأمد، ويقدمه إلى npm، ويحصل في المقابل على تصريح نشر. تصدر الإصدارات بشهادات منشأ (provenance)، فيمكن لأي شخص تتبع المكان الذي بُنيت فيه الحزمة.
يزيل هذا التصميم فئة كاملة من حوادث تسريب الأسرار. لكنه أيضاً أدخل نمط فشل دقيقاً بسبب حقل واحد.
ربطت npm علاقة الثقة بالعنوان المقروء للمستودع: owner/repository. وتحمل رموز OIDC من GitHub أيضاً المعرّف الرقمي الدائم للمستودع، وهو معرّف يصمد أمام إعادة التسمية والنقل. لكن npm، حتى أول نشر ناجح للحزمة، تجاهلت ذلك الرقم تماماً واكتفت بمطابقة الاسم.
الأسماء تتحرك. تصبح متاحة عندما يعيد المشرف تسمية المستودع أو ينقله أو يحذفه، وبمجرد أن يصبح الاسم متاحاً يمكن لأي شخص انتزاعه.
كيف تعمل SlugFest فعلياً
- يضبط أحد المشرفين النشر الموثوق لحزمة ما، لكنه لم ينشر بعد أي إصدار من ذلك المستودع، فيبقى الربط قائماً على الاسم.
- يعيد المشرف تسمية المستودع أو ينقله أو يحذفه. فيصبح الـ slug القديم
owner/repositoryمتاحاً. - ينشئ المهاجم مستودعاً جديداً بالضبط على ذلك الـ slug المحرَّر ويشغّل سير عمل نشر. فيصدر GitHub رمز OIDC يحمل الاسم المستعاد مع معرّف مستودع جديد تماماً.
- تتحقق npm من الاسم، فتجد أنه يطابق الإعدادات المحفوظة، وتمنح رمز نشر لحزمة لا يملكها المهاجم.
من هناك ينشر المهاجم نسخة خبيثة تحت اسم الحزمة الشرعي. وتأتي معها أعداد التنزيلات والسمعة وكل المشاريع المعتمدة عليها. وجد مسح Bloom على مستوى السجل أكثر من 1,500 حزمة معرضة للخطر بإجمالي يزيد على 10 ملايين تنزيل وأكثر من مليون تنزيل شهرياً.
أبلغت Bloom شركة GitHub في 6 يونيو 2026، وصُنّفت الثغرة في 9 يونيو. ثم برد الأثر خلال يوليو، ولم يأتِ الإصلاح إلا عندما استعد الباحثون للنشر، بعد أكثر من 120 يوماً. وقد أكدت GitHub وnpm المعالجة واعتذرا عن بطء التواصل.
الإصلاح جاء بالشكل الصحيح تماماً: إعدادات النشر الموثوق المنشأة حديثاً تنتهي صلاحيتها الآن بعد 48 ساعة ما لم تكمل أول عملية نشر ناجحة، وهي ما يربط الثقة بالهوية الثابتة للمستودع. وتغيير هوية المستودع أو المشروع يتطلب علاقة ثقة جديدة ونافذة تحقق جديدة مدتها 48 ساعة. كما توقفت npm عن قبول رموز النشر الموثوق الصادرة من أحداث issue_comment، إضافة إلى القيد القائم على pull_request_target.
ثم وصل الوكلاء
لو كانت SlugFest تتعلق فقط بمطورين بشريين يشغّلون npm install، لكان الأمر خطيراً بالفعل. لكن النصف الثاني من بحث Bloom هو ما يجب أن يغيّر طريقة تفكيرك في خط البناء الخاص بك.
درس Bloom ملايين الوكلاء الاصطناعيين في العشرات من المؤسسات. يستقبل الجهاز النموذجي نحو 70 حزمة يثبتها الوكلاء كل شهر. أما أجهزة المطورين فهي تقترب من 350. ويثبّت كل وكيل ما بين 0.3 و1.2 حزمة يومياً، فيما تتراوح عمليات التثبيت المباشر على أجهزة المطورين بين عمليتين وثلاث يومياً، إضافة إلى كل ما تجره تلك الحزم معها. ويشغّل الجهاز النموذجي ثلاثة وكلاء بين واجهات سطر الأوامر وبيئات التطوير والإضافات والمساعدين، فيما تشغّل أجهزة المطورين خمسة أو أكثر.
الآن ضع هذا إلى جانب سلوك الوكيل. فهو يحل الاعتماديات بنفسه، ويفضّل أحدث إصدار، ونادراً ما يسأل من أين جاءت الحزمة. ونسخة خبيثة منشورة عبر slug مستعاد تُثبَّت ويُنفَّذ خطاف postinstall الخاص بها دون أي إنسان في الحلقة.
رصدت Bloom ذلك في بيئة إنتاج فعلية، إذ حجبت وكيل ذكاء اصطناعي لأحد العملاء وهو يحاول تثبيت إحدى الحزم المتأثرة.
مكسب المهاجم سلسلة متتالية: اختراق حزمة واحدة، ويسحبها وكيل ذكاء اصطناعي على جهاز مشرف مشهور، فيصبح ذلك الجهاز منصة لإطلاق نسخة خبيثة من حزمة المشرف نفسه، ويُصبح كل مستهلك لها مكشوفاً. إنه نمط Shai-Hulud مع مسرّع.
المنشأ ليس مربعاً نضع فيه علامة
هناك نقطة عمياء ثانية تستحق الانتباه، لأنها من النوع الذي ينجو من تدقيق الامتثال.
يمكن أن تحمل نسخة خبيثة شهادة منشأ صادرة من مستودع المهاجم نفسه. وبعض أنظمة التحقق تفحص فقط وجود الشهادة، لا تطابق مصدرها مع المشرف الذي كان يُفترض أن تأتي الحزمة منه. التوقيع حقيقي، لكن الموقّع هو الشخص الخطأ. وهنا يجب أن ينتقل التحكم بسلسلة التوريد من "هل كان موقّعاً؟" إلى "هل وقّعته الهوية التي أثق بها، وهل لا تزال هذه الهوية هي نفس الكائن الذي وثقت به الشهر الماضي؟".
تجدر الإشارة إلى أن Warehouse التابع لـ PyPI يخزن بالفعل معرّفات ثابتة، وهو ما أوصت به Bloom لـ npm. كما عانى مسار النشر الموثوق عبر GitLab في npm من الضعف نفسه.
ماذا يعني ذلك لعملاء aratech
لا تستطيع معظم المؤسسات إصلاح سجل حزم، ولن تتوقف عن استخدام npm. لكن ما يمكنها فعله هو التوقف عن التعامل مع وصول الحزم كحدث غير مرئي.
- دقّق روابط النشر الموثوق اليوم. على المشرفين الذين يملكون صلاحيات النشر تشغيل
npm trust listوالتأكد من أن كل slug مُعدّ لا يزال يشير إلى مستودع تحت سيطرتهم. وأي ربط يشير إلى مستودع أُعيدت تسميته أو نُقل أو حُذف يجب حذفه وإعادة إنشائه. - تعامل مع نظافة المستودعات كعمل أمني. يجب أن يكون حذف ربط الثقة عند كل إعادة تسمية أو نقل أو حذف خطوة مكتوبة في دليل التشغيل، لا نية طيبة.
- ضع بوابة أمام مسار التثبيت. جدار حماية لسلسلة التوريد يقرر ما يدخل البيئة هو الضابط القابل للتوسع فعلاً، لأنه لا يعتمد على إنسان يراجع فرق ملف lockfile في السادسة مساءً.
- وسّع الجرد ليشمل ما هو أكثر من الحزم. دقّق الإضافات والمكونات وخوادم MCP والمهارات والتطبيقات. وجدت Bloom النمط نفسه في أغسطس في Open VSX وسوق VS Code: 87 حزمة إضافات في الأول و677 في الثاني كانت تشير إلى إضافات غير موجودة، متاحة لأي شخص ينتزعها.
- اكتب سياسة الوكلاء. أي الوكلاء يمكنهم تثبيت البرمجيات، ومن أي سجلات، وبأي موافقة، وكيف ستعرف ذلك لاحقاً.
النمط الذي يستحق التذكر
تظل قصص الأمن المرتبطة بالذكاء الاصطناعي على مدى عامين تدور حول الدرس نفسه، وتصوغه SlugFest بوضوح: الربط بين اسم مقروء والشيء الذي يحدده هو الثابت الأهم في أي نظام ثقة. اكسره بإعادة تسمية روتينية، وينهار الضمان، بصمت، دون تنبيه ودون أي تسجيل دخول فاشل.
وكلاؤك أصبحوا جزءاً من البنية التحتية. إنهم يثبتون الشيفرة بسرعة الآلة في بيئات أنت مسؤول عنها. توقف الاسم على الباب عن كونه دليلاً على من بالداخل. تحقق من الهوية لا من التهجئة، وافعل ذلك تلقائياً.