دودة خبيثة تستهدف سلاسل التوريد في حزمة جافاسكربت عبر npm وتسرق بيانات الاعتماد
في الرابع من أغسطس 2026، ظهر تهديد جديد على نظام npm—ليس كحزمة عابرة، بل كـ[دودة] (Worm) متخصصة في سرقة بيانات الاعتماد داخل بيئات التطوير والتكامل المستمر. ما يجعل الحادث مختلفًا وخطيرًا هو أن “الانتشار” لم يكن مجرد تلاعب بحزمة واحدة، بل توسّع عبر مئات الحزم المرتبطة بعشرات—بل مئات—الأسماء داخل سجلات npm لدى عدة مؤسسات، وفقًا لتحليلات [SafeDep] و[Socket] و[Aikido].
بالنسبة لفرق الأمن السيبراني، هذا النوع من الهجمات يضعنا أمام حقيقة مزعجة: سلاسل التوريد البرمجية لم تعد “خطرًا نظريًا”. إنها مسار عملي للوصول إلى المفاتيح والرموز داخل أنظمة CI وبيئات المطورين، حيث تكون بيانات الاعتماد أكثر قابلية للاستخراج لأن الأوامر تُشغَّل تلقائيًا ولأن الثقة تُمنح ضمنيًا.
وفقًا لبيانات [SafeDep]، تم التحقق من 353 نسخة “مسمومة” عبر 79 اسم حزمة داخل سجل npm. ثم أضافت [SafeDep]—عبر المراقبة—أن هناك 442 نسخة عبر 353 اسمًا، بينما قدّمت [Aikido] رقمًا أعلى من زاوية مختلفة: 868 حزمة عبر 1,381 نسخة. الأهم: هذه الأرقام تقيس حجم الأثر في السجل (نسخ/أسماء الحزم)، ولا تُثبت وحدها عدد الأجهزة التي نفّذت الحمولة.
أول إصدار مؤكد للهجوم كان keyv@6.0.0. ومن هناك، تحركت الدودة خارج نطاق Keyv وضمن نطاقات أخرى عبر موجات نشر سريعة. في تحديث لاحق بتاريخ 4 أغسطس، توسّع عدّاد [SafeDep] ليصل إلى 1,684 نسخة مدمّرة عبر 420 اسم حزمة مرتبطة بـ9 مؤسسات—مع تقدير بأن الانتقال بين المؤسسات كان يتم كل 2 إلى 7 دقائق وأن اندفاع النشر عبر مؤسسات متعددة اكتمل خلال نحو نصف ساعة.
كيف تعمل الدودة؟ (لماذا تُستهدف بيئات التطوير وCI؟)
الآلية الجوهرية للهجوم تعتمد على استغلال خطاف التثبيت في npm. النسخة الخبيثة تضيف سكربت ضمن preinstall ليقوم بتشغيل “حزمة سرقة بيانات” داخل بيئات المطور وبيئات [CI] (التكامل المستمر). هذا يعني أن الهجوم يحدث غالبًا قبل أن تبدأ عملية البناء أو الاختبارات، وبذلك تكون فرصة استخراج الأسرار أعلى.
بحسب تحليل [SafeDep] و[Socket]، يمكن للحمولة أن تستخرج مجموعة واسعة من المواد الحساسة، تشمل:
- بيانات من [GitHub] و[GitHub Actions] و[سجل npm]
- معلومات من منصات سحابية ومواد خاصة بمفاتيح [Vault]
- بيانات مرتبطة بـ[ Kubernetes ] (عند وجود إعدادات)
- محتوى من ذاكرة [GitHub Actions runner] عند توفره
- مخزون “مفاتيح خاصة” أو رموز وصول مخزنة ضمن بيئة العمل
الأخطر هنا ليس فقط السرقة، بل السلوك اللاحق: الدودة تملك آلية لاستغلال حق النشر المتاح في npm لتسميم حزم إضافية—أي أنها لا تكتفي بالاختراق، بل تتحول إلى منصة انتشار داخل النظام نفسه.
مسار إضافي داخل أدوات المطور: Claude Code وVS Code
الهجوم لم يقتصر على مسار npm وحده. فالمستودع الخاص بـ Keyv احتفظ بملفات إعدادات لهدفي تنفيذ مختلفين: [Claude Code] و[VS Code]. وفقًا للباحثين، توجد مسارات تنفيذ مرتبطة بـ:
- ملف .claude/settings.json مع خطاف SessionStart يستدعي سكربت إعداد
- ملف .vscode/tasks.json حيث توجد مهمة runOn: folderOpen تستدعي سكربت إعداد آخر
هذه النقطة مهمة لأن تنفيذ المهام في بيئات التطوير يتأثر بـ[ثقة مساحة العمل] (Workspace Trust). في [VS Code] غالبًا توجد قيود تمنع التشغيل التلقائي في المساحات غير الموثوقة، مع طلب موافقة. أما [Claude Code] فيطبق مفهوم الثقة على مستوى مساحة العمل بناءً على إعدادات المستخدم. النتيجة: ليس كل من “يسحب” المشروع سيُصاب تلقائيًا، لكن من يثق بالمستودع أو يفتح مجلدًا ضمن سياق موثوق قد يشغّل الحمولة.
تفاصيل الإصدار: ماذا تغيّر في keyv@6.0.0؟
بحسب [SafeDep]، لم يتغير “الكود المُجمّع” الأساسي للحمولة بشكل كبير، لكن تم إدخال node setup.mjs ضمن preinstall. كما تضمنت الحزمة ملفات إضافية مثل setup.mjs وMath_Symbol.js ضمن المحتوى المنشور.
على مستوى التنفيذ، تمر الحمولة غالبًا عبر خطوة تحقق من وجود [Bun]. وإذا لم يكن موجودًا، يتم تنزيل نسخة 1.3.13 من الإصدارات الرسمية للمشروع، ثم تسليم التنفيذ إلى “حزمة مُجمّعة” كبيرة الحجم (بحسب التقارير نحو 727,680 بايت). هذا النمط—دمج تنزيل وقت التشغيل مع تنفيذ حمولة—يعقّد التحليل ويزيد من خطر “التحليل الساكن” الذي يفشل إذا لم تُلتقط مرحلة التنفيذ الفعلية.
لماذا تمر الهجمات رغم وجود توقيعات وإثباتات منشأ؟
من اللافت أن الإصدار الخبيث مر عبر سير عمل النشر الشرعي في [GitHub Actions]، وحمل سجلات OpenID Connect (OIDC) وSLSA (Levels for Software Artifacts) بشكل صحيح—أي أن “الإثبات” يوضح أن البناء تم عبر مسار مشروع معروف، لكنه لا يثبت أن المصدر الذي دخل إلى البناء كان آمنًا.
هذه هي المفارقة التي تواجهها فرق الامتثال الحديثة: سلسلة التوثيق قد تكون سليمة تقنيًا، بينما تكون المدخلات نفسها قد تم العبث بها—سواء عبر استيلاء على حساب نشر، أو عبر إدخال ملفات خبيثة داخل مستودع، أو عبر تعديل مسارات البناء قبل الإصدار.
ماذا يعني “تسميم” الحزم؟ ولماذا لا تكفي قائمة حظر على مستوى النطاق؟
تسميم الحزم في npm يعني أن المهاجمين ينشرون نسخًا تبدو شرعية (بنفس الاسم وتوافق الواجهات)، لكنها تحمل سكربتات lifecycle خبيثة. في هذا الحادث، تم تغيير “tags” في السجل بسرعة بحيث تظهر الإصدارات الخبيثة كأنها “الأحدث” لبعض الحزم.
لكن الباحثين حذروا من الاعتماد على قائمة ثابتة لحظر أسماء الحزم أو الوسوم. السبب:
- الوسوم تتغير بسرعة في السجل، ما يجعل “latest” غير مستقر كمرجع
- ليس كل ما يرتبط بمؤلف الحزمة كان خبيثًا؛ فبعض مسارات @keyv/* أو سلاسل Keyv 5.x كانت نظيفة
- لا يمكن دائمًا استنتاج الإصابة دون معرفة النسخة المحلولة على الجهاز (resolved version) ووجود تشغيل lifecycle فعلي
لذلك، النهج الصحيح هو فحص lockfiles ومخططات الاعتماد (dependency graphs) وربطها بالنسخ الفعلية التي تم تثبيتها، بدلًا من الاكتفاء بتخمينات مبنية على “الحالة الحالية” لصفحات npm.
ما المخاطر الأمنية المباشرة؟
إذا تم تشغيل نسخة متأثرة داخل بيئة تطوير أو runner، فهناك احتمالان كبيران:
- سرقة الأسرار: رموز وصول لـGitHub، رموز npm، مفاتيح سحابية، أسرار Kubernetes، وأي بيانات اعتماد موجودة في بيئة التشغيل
- استمرار الوصول: عبر مراقب لإبطال الرموز (credential-revocation watcher) أو عبر آليات لاحقة لإعادة استغلال الهوية
وبحسب [SafeDep]، توجد “مراقبة لإبطال الرموز” تعمل كشرط للتفعيل. وهذا يخلق خطرًا تكتيكيًا في الاستجابة: إذا قامت الفرق بتدوير الرموز أولًا، فقد تنفذ الدودة “معالجًا محليًا” تم توفيره ضمنيًا من قبل المهاجمين أثناء مرحلة التثبيت. لذا يُنصح بالتعامل مع الاستجابة على مراحل، مع إزالة آلية المراقبة قبل البدء بعملية التدوير.
مقارنة مع اتجاهات أوسع: من الهجمات المستهدفة إلى موجات الانتشار
الهجمات على سلاسل التوريد شهدت تطورًا واضحًا خلال السنوات الأخيرة. نحن نرى انتقالًا من “ملفات ضارة داخل حزمة واحدة” إلى هجمات تقوم بـ:
- استغلال lifecycle scripts (مثل preinstall وpostinstall)
- استخدام مسارات نشر آلي لتوسيع نطاق الضرر
- تلاعب سريع بالوسوم لتضليل أنظمة الاعتماد
- دمج مسارات داخل أدوات المطور لزيادة فرص التنفيذ
على سبيل المثال، لا يزال [OWASP] يضع مخاطر سلسلة التوريد والاعتماد ضمن أعلى فئات المخاطر، بينما تؤكد أطر مثل [NIST] (خصوصًا مبادئ إدارة المخاطر) أن التحقق لا يجب أن يتوقف عند “وجود توقيع” أو “وجود إثبات منشأ”، بل يجب أن يمتد إلى سلامة المصدر والتحكم في مسارات البناء.
كما أن [npm 12]—بحسب ما أشار إليه الباحثون—تقوم بحجب سكربتات lifecycle غير المصرح بها افتراضيًا. لكن هذا لا يغلق الباب أمام الهجوم بالكامل، لأن العملاء الأقدم أو طرق التثبيت الأخرى قد تسمح بتنفيذ lifecycle scripts، ولأن بيئات CI قد تكون مهيأة بشكل مختلف.
كيف يجب أن تتصرف الفرق؟ (خطة عملية بدلًا من رد فعل متأخر)
التقارير تشير إلى أن الحزم الخبيثة تم إزالتها لاحقًا من بعض الأسماء، لكن “latest” قد كان لا يزال يشير إلى نسخ خبيثة في وقت التحديث. لذلك، فإن الترقية وحدها قد لا تكون كافية لأن الخطر يعتمد على ما تم تثبيته فعليًا وليس فقط ما هو متاح الآن.
إجراءات موصى بها—بشكل عملي وقابل للتنفيذ—تشمل:
- مقارنة lockfiles ونسخ الاعتماد المحلولة مقابل قائمة الأسماء والنسخ المتأثرة بدقة
- تعطيل السكربتات غير الضرورية المرتبطة بمرحلة التثبيت (lifecycle scripts) قدر الإمكان
- اعتبار أي runner أو workstation نفّذ إصدارًا متأثرًا كأنه مُعرّض لسرقة بيانات الاعتماد
- إزالة “مراقب إبطال الرموز” قبل تدوير الرموز والاتصالات—ثم تنفيذ تدوير منظم
- تطبيق مبدأ least privilege على حسابات النشر وCI لتقليل أثر الاستحواذ على الهوية
ولأن هذه ليست مجرد مشكلة “كود”، بل مشكلة هوية وتوزيع، فإن فرق الأمن يجب أن تراجع أيضًا سياسات الوصول إلى مفاتيح النشر وبيانات الاعتماد داخل CI/CD، وتأكد من وجود مراقبة لسلوك نشر غير معتاد على npm وGitHub.
لماذا ما زالت أسئلة التحقيق مفتوحة؟
لم تُحسم بعد مسألة “من أين بدأت” على نحو كامل. لا تُظهر الأدلة بشكل قاطع ما إذا كان الانتشار نتج عن هوية نشر واحدة تم اختراقها أو عن اعتمادات متعددة تم اختراقها في نفس الوقت. كما لم يظهر بيان علني من المالكين أو من [npm] أو [GitHub] عند نقطة جمع البيانات.
حتى وجود شارات تحقق على مستوى [GitHub Verified] لا يحدد الجهة التي كانت تملك “القدرة” على إصدار التعديل، لأن التوقيع والتحقق يثبتان سلامة مسار التوقيع لا سلامة نوايا المصدر أو السيطرة على بيانات الاعتماد التي نفذت العملية.
أثر جانبي يستحق الانتباه: مستودعات تحمل وصفًا مشابهًا
سجّل الباحثون إنشاء 546 مستودعًا عامة في [GitHub] بتاريخ 4 أغسطس بوصف يتضمن عبارة مرتبطة بعائلة الهجوم (مثل “Shai-Hulud: Here We Go Again”). لكن هذا لا يعني وجود 546 ضحية مؤكدة؛ قد تكون المستودعات مجرد منصات staging أو قنوات إخراج بيانات أو بقايا تجارب. لذلك يجب التعامل معها كمؤشرات بحثية لا كإثبات إصابة نهائي.
الخلاصة: ما الدرس الأهم لفرق الأمن؟
هذه الحادثة تذكّرنا بأن سلاسل التوريد ليست “سلسلة” واحدة، بل شبكة من الثقة: من npm إلى أدوات التطوير إلى أدوات البناء والـCI، وصولًا إلى آليات التوقيع والتوثيق. عندما تُستغل lifecycle scripts وتتوسع موجات النشر عبر عدة مؤسسات، تصبح الحماية مجرد طبقة واحدة ضمن منظومة أوسع.
في النهاية، السؤال الذي يهم المؤسسات ليس فقط: “هل توجد نسخة خبيثة؟” بل: هل لدينا رؤية دقيقة لما تم تثبيته فعليًا؟ وهل يمكننا عزل بيئات التطوير والـCI بسرعة قبل أن يتحول الأمر إلى سرقة أسرار واسعة؟
سؤال للنقاش
إذا تم استدعاء مشروعكم إلى بناء تلقائي في [CI] باستخدام حزم JavaScript، ما مدى ثقتكم بأنكم تستطيعون خلال ساعات—وليس أيام—تحديد: أي نسخة تم حلها، وهل تم تشغيل lifecycle scripts، وما هي الرموز التي كانت متاحة وقت التنفيذ؟
مصادر وإشارات إضافية
للتواصل أو متابعة محتوى مشابه:
وسوم مقترحة: #سلاسل_التوريد #أمن_البرمجيات #حماية_CI #سرقة_بيانات_الاعتماد

Leave a Reply