npm v12: چرا بستن اسکریپتهای نصب کافی نیست
خلاصهٔ کاملتر
نویسنده که سالهاست روی امنیت اکوسیستم Node.js کار میکنه، میگه npm v12 بالاخره اجرای خودکار اسکریپتهای نصب رو خاموش میکنه؛ تغییری که خودش سالها منتظرش بوده. ولی به گفتهٔ نویسنده این کار یه در رو میبنده و در بعدی رو باز میذاره.
سه تغییر مهم اینه: پیشفرض allowScripts خاموش میشه، پس npm install دیگه اسکریپتهای preinstall/install/postinstall یه پکیج رو خودکار اجرا نمیکنه و حتی node-gyp rebuild ضمنیِ پکیجهای دارای binding.gyp هم بلاک میشه. --allow-git و --allow-remote هم پیشفرض none میشن تا وابستگیهای Git و ریموت بدون اجازه resolve نشن.
نویسنده یادآوری میکنه چرا این hookها هدف محبوب مهاجم بودن: خودکار، با دسترسی کاربر و قبل از اینکه کسی حتی یه خط کد رو ببینه اجرا میشن. حملههای واقعی سال گذشته مثل دستکاری chalk و debug، کرم خودتکثیرشوندهٔ Shai-Hulud و بعد Miasma که بهجای postinstall از همون binding.gyp سوءاستفاده کرد، همه از همین مسیر اومدن.
نکتهٔ اصلی مقاله اینه که npm install درخت وابستگی رو دانلود و اسکریپتهای lifecycle رو اجرا میکنه، ولی بدنهٔ ماژول رو require نمیکنه. پس با بستن اسکریپت نصب، مهاجم payload رو میذاره تو بدنهٔ ماژول بهشکل یه side effect سطحبالا (مثل یه IIFE) که لحظهٔ import اجرا میشه. یعنی npm v12 فقط یه trigger رو حذف میکنه، نه یه capability رو.
به گفتهٔ نویسنده راهحل واقعی اینه که بهجای جلوگیری از اجرای کد، محدود کنی کدِ درحالاجرا چیکار میتونه بکنه. مدل دسترسی Node.js دقیقاً همینه؛ با فلگ --permission هر قابلیت تا وقتی صریحاً grant نشه رد میشه:
node --permission \
--allow-fs-read=/app \
--allow-net=api.mycompany.com \
app.jsبا این حالت همون payload بازم اجرا میشه، ولی child_process بدون --allow-child-process، شبکه بدون --allow-net و نوشتن فایل بدون --allow-fs-write بلاک میشن؛ پس دادهٔ دزدیدهشده جایی برای رفتن نداره. البته نویسنده صادقانه میگه خوندن process.env گیت نمیشه و خود Node این مدل رو مرز امنیتی نمیدونه، فقط شعاع خرابی رو کم میکنه.
جمعبندی نویسنده اینه که لایهها رو روی هم بذاری: allowScripts خاموش، --permission برای stepهای Node و کنترل egress سطح runner (مثل Harden-Runner) تو CI که پر از توکن و کلیده. حرف آخرش اینه که هیچ کنترل تنهایی کافی نیست و امنیت زنجیرهٔ تأمین یه دفاع چندلایهست.
نکات کلیدی:
- npm v12 اجرای خودکار اسکریپتهای نصب و node-gyp rebuild ضمنی رو پیشفرض خاموش میکنه.
- بعد از بستن install-time، بدافزار به execution-time و بدنهٔ ماژول کوچ میکنه.
- مدل دسترسی Node با --permission دسترسی به فایل، شبکه و child process رو محدود میکنه.
- خوندن env گیت نمیشه و این مدل مرز امنیتی نیست، فقط شعاع خرابی رو کم میکنه.
- دفاع مؤثر یعنی چندلایه: اسکریپت خاموش، permission model و کنترل egress تو CI.




