شارة provenance في npm ليست فحص أمان: درس دودة tensorlake
شارة المصدر provenance الخضراء على حزمة npm تخبرك أين بُنيت الحزمة، ولا تخبرك أن الكود آمن. بحسب متتبّع الحوادث pwn.watch، نُشر الإصدار tensorlake@0.5.144 يوم 8 أكتوبر 2026 من مستودع المشروع الحقيقي على GitHub، ومعه شهادة مصدر من npm، وكان يحمل خطّاف preinstall يثبّت دودة لسرقة بيانات الاعتماد من نوع Shai-Hulud. إن كان فريقك يعامل هذه الشارة كعلامة ثقة، فهذه الحالة تستحق القراءة، لأن الشارة كانت حقيقية.
ما يرويه المتتبّع
كل ما في هذا القسم ملخص المتتبّع، أي رواية جهة تجميع واحدة، والمرجع الذي تتحقق منه قبل أي خطوة هو التنبيه الرسمي للحزمة نفسها. يصنّف المتتبّع الحادثة على أنها مُصلحة جزئيًا. ويقول إن الخطّاف يجمع أسرار npm وGitHub والسحابة وSSH وأدوات الذكاء الاصطناعي، وينتشر إلى حزم أخرى، ويثبّت مراقبًا اسمه gh-token-monitor يمسح المجلد الرئيسي للمستخدم إذا أُلغي رمز GitHub المسروق. ونصيحته: ثبّت الإصدار 0.5.143، وأزل ذلك المراقب قبل تدوير الرموز. هذه النقطة الأخيرة تعاكس ردّ الفعل المعتاد بالإلغاء أولًا، ولهذا هي مهمة.
ما تثبته شهادة المصدر وما لا تثبته
هذه معرفة عامة بطريقة عمل الشهادة. شهادة المصدر بيان موقّع بأن مستودعًا معينًا وسير عمل معينًا أنتجا هذه الحزمة. هي تسدّ ثغرة واحدة جيدًا: من ينشر نسخة مقلّدة من جهازه برمز مسروق لا يستطيع تزويرها. لكنها لا تقول شيئًا عن سلامة الكود الموجود في المستودع في تلك اللحظة. إن دخل مهاجم إلى خط البناء أو إلى حساب أحد المشرفين، فالإصدار الخبيث يُبنى من المستودع الحقيقي ويحمل شهادة حقيقية.
تعمل GitHub على تشديد جهة النشر. يقول سجل التغييرات لديها إن إعدادات النشر الموثوق في npm التي لا يُتحقق منها تنتهي الآن بعد 48 ساعة، وإن رموز النشر الموثوق القادمة من أحداث issue_comment تُرفض، وإن الأمر npm stage publish يتطلب أن يرقّي أحد المشرفين أول إصدار من أي حزمة جديدة. وتقول GitHub أيضًا إن البرمجيات الخبيثة تعمل بشكل متزايد وقت التثبيت، فتجمع بيانات الاعتماد من أجهزة التكامل المستمر ومحطات العمل دون أن يشغّل تطبيقك كود الحزمة أصلًا. هذا هو شكل الحادثة بالضبط، ولهذا يجب أن يكون الدفاع عند خطوة التثبيت.
الطريق من npm install إلى أسرارك
معرفة عامة مرة أخرى: سكربتات preinstall وinstall تعمل أثناء npm install بصلاحيات المستخدم نفسه، فكل ما تستطيع الطرفية قراءته يستطيع السكربت قراءته. على جهازك هذا يعني مفاتيح SSH وإعدادات السحابة، وعلى خادم التكامل المستمر يعني كل سرّ مُمرَّر إلى المهمة.
القطع الأول، اختر ما يُثبَّت. احفظ ملف القفل في المستودع وثبّت منه، فلا يصل إصدار جديد إلا حين تقرر أنت. وفترة الانتظار، أي ألّا تعتمد إصدارًا عمره أقل من بضعة أيام، تمنحك وقتًا، لأن الإصدارات الخبيثة كثيرًا ما تُكتشف خلال أيام. جدار الحزم من GitHub، وهو في معاينة عامة لعملاء Enterprise Cloud ولـnpm فقط، يوفّر فترة انتظار قابلة للضبط من هذا النوع. القطع الثاني، لا تشغّل سكربتات التثبيت افتراضيًا. الأمر npm ci --ignore-scripts يتخطاها، وبعض الحزم تحتاج سكربتاتها فعلًا، فاسمح لتلك عن قصد. القطع الثالث، أبعد الأسرار عن خطوة التثبيت. مهمة التكامل المستمر التي تثبّت الاعتماديات لا تحتاج مفاتيح النشر في بيئتها.
npm ci --ignore-scripts
npm ls tensorlake
إن عمل tensorlake 0.5.144 على أحد أجهزتك
الترتيب العام: اعزل الجهاز أو خادم البناء، واعرف ما الذي عمل عليه، ثم دوّر كل سرّ كان بإمكانه قراءته، من جهاز نظيف. وفي هذه الحالة تحديدًا، بحسب ما يذكره المتتبّع، ابحث عن مراقب الرمز وأزله قبل إلغاء رمز GitHub. وتحقق من كل خطوة في التنبيه الرسمي للحزمة، لا في هذا الملخص وحده.
المصدر: متتبّع الحوادث pwn.watch، مدخل tensorlake@0.5.144.
ملاحظات القراء