Loading blog posts...
Loading blog posts...
جاري التحميل...

صدرت npm v12 في 8 يوليو 2026، وأحدثت تغييراً صامتاً لكنه جذري: npm install لم يعد ينفذ أكواد الحزم تلقائياً كما كان من قبل. أصبحت سكريبتات التثبيت معطلة افتراضياً ما لم توافق عليها صراحةً. إذا كان خط CI الخاص بك يعتمد على حزم مثل sharp أو esbuild أو node-sass، فهناك احتمال كبير أن فشل البناء في انتظارك. المشكلة الأصعب؟ غياب الملفات الثنائية الأصلية لا يؤدي دائماً لفشل البناء. قد تحصل على CI ناجح تماماً، لكن المشكلة تنفجر لاحقاً عند التشغيل الفعلي.
يؤكد سجل التغييرات في 8 يوليو أن npm v12 حولت تنفيذ السكريبتات وقت التثبيت من تلقائي إلى موافقة صريحة. هذا يتجاوز سكريبتات postinstall المعتادة. إليك ما أصبح محظوراً افتراضياً:
| نوع التنفيذ | السلوك السابق | الافتراضي في npm v12 |
|---|---|---|
سكريبتات preinstall و install و postinstall | تنفيذ تلقائي | محظور |
بناء node-gyp عبر binding.gyp | تنفيذ تلقائي | محظور |
سكريبتات prepare لاعتماديات git/file/link | تنفيذ تلقائي | محظور |
| اعتماديات git المباشرة | مسموح | allow-git=none |
| مصادر URL/tarball البعيدة | مسموح | allow-remote=none |
التغيير في binding.gyp هو ما يفاجئ الفرق عادةً. الحزمة لا تحتاج لسكريبت postinstall واضح لتنفيذ كود أثناء التثبيت. إذا احتوت على binding.gyp، كان node-gyp يبدأ البناء تلقائياً. هذا المسار أصبح مغلقاً الآن.
Warning
الحزم التي تحتوي على ملفات binding.gyp قد تُثبّت دون أخطاء لكنها تنتج ملفات ثنائية غير وظيفية. سيظهر CI باللون الأخضر حتى تحاول الاختبارات أو الإنتاج استخدام الوحدة الأصلية فعلياً.
أرقام الهجمات في 2025-2026 جعلت "الانتظار والترقب" غير واقعي. أشار تقرير Sonatype لعام 2026 إلى أكثر من 454,600 حزمة خبيثة جديدة في 2025، أكثر من 99% منها جاءت من npm. الربع الرابع من 2025 وحده سجل 394,877 حزمة خبيثة جديدة: زيادة 476% مقارنة بالأرباع الثلاثة السابقة مجتمعة.
حادثتان بالتحديد دفعتا الأمور لهذا الحد. دودة "Shai-Hulud" في سبتمبر 2025 حقنت سكريبتات postinstall خبيثة في حزم شائعة، وانتهى الأمر بإزالة أكثر من 500 حزمة مخترقة. الأخطر كانت "Miasma" (تُسمى أيضاً "Phantom Gyp")، التي وثقتها Chainguard بإصابة 57 حزمة عبر 286 إصدار خبيث. Miasma لم تعتمد على سكريبتات postinstall واضحة. استغلت binding.gyp وسلوك node-gyp لتنفيذ كود دون تفعيل الإنذارات المعتادة. الماسحات التي بحثت فقط عن سكريبتات postinstall مشبوهة فاتتها تماماً.
لماذا هذا مهم: الخطر لم يقتصر على "الحزم التي تحتوي postinstall". كان أي اعتمادية يمكنها تشغيل ترجمة أصلية. npm v12 تحظر مسار الهجوم بالكامل افتراضياً.

هنا تصبح الترقية لـ npm v12 معقدة. حظر سكريبت التثبيت لا يعني بالضرورة فشل npm ci.
bashnpm ci # ✅ كود الخروج 0 # ✅ node_modules مملوء # ❌ الملفات الثنائية الأصلية مفقودة أو غير وظيفية
يمكن لـ npm ci النجاح لأن أجزاء JavaScript تُثبّت بشكل طبيعي. خطوة البناء الأصلية التي كانت تعمل أثناء التثبيت ببساطة لا تحدث. يستمر خط الإنتاج. قد تنجح اختباراتك حتى إذا لم تصل لمسارات الكود الأصلية. ثم يحاول الإنتاج تغيير حجم صورة باستخدام sharp، وفجأة يتضح أن الملف الثنائي لم يُبنَ أبداً.
javascript// هذا الاستيراد ينجح const sharp = require('sharp'); // هذا يفشل عند التشغيل sharp('input.jpg').resize(300, 200).toFile('output.jpg'); // Error: Could not load the "sharp" module using the linux-x64 runtime
لاكتشاف هذا مبكراً، تحتاج اختبارات دخان تستخدم الوحدات الأصلية فعلياً، وليس فقط استيرادها.
javascript// ci-smoke-test.js const sharp = require('sharp'); const canvas = require('canvas'); // استخدم الربط الأصلي فعلياً await sharp(Buffer.from([0x89, 0x50, 0x4e, 0x47])).metadata; console.log('sharp: OK'); const ctx = canvas.createCanvas(1, 1).getContext('2d'); console.log('canvas: OK');
شغّل شيئاً مثل هذا بعد npm ci لاكتشاف الفشل الصامت قبل وصوله للإنتاج. ما يُفوّت غالباً: استيراد وحدة أصلية قد ينجح حتى لو كان الملف الثنائي تحتها معطوباً. تحتاج للاستدعاء الفعلي.

تضيف npm v12 آلية موافقة على مستوى المشروع عبر حقل allowScripts الجديد في package.json. توثيق approve-scripts يشرح آلية العمل بالكامل.
bash# الخطوة 1: تحديد الحزم ذات سكريبتات التثبيت غير المراجعة npm approve-scripts --allow-scripts-pending
هذا يطبع الحزم التي لديها سكريبتات تثبيت لكنها ليست في قائمة الموافقة بعد. راجع كل واحدة بعناية. في معظم الحالات، المفاجآت هي اعتماديات متعدية لم يختارها فريقك مباشرة.
bash# الخطوة 2: الموافقة على الحزم الموثوقة npm approve-scripts sharp npm approve-scripts esbuild npm approve-scripts @prisma/client
الموافقات مثبتة على الإصدار افتراضياً. لذا إذا أصدرت sharp إصداراً جديداً، لن ترث الموافقة تلقائياً. هذه هي النقطة: تفرض إعادة فحص متعمدة.
json{ "allowScripts": { "sharp@0.33.4": true, "esbuild@0.21.5": true, "@prisma/client@5.15.0": true, "suspicious-package@1.0.0": false } }
تثبيت الإصدار هو ما يقوم بالعمل الأمني الحقيقي هنا. إذا اخترق مهاجم حساب مشرف وأرسل تحديثاً خبيثاً، لن يحصل ذلك التحديث تلقائياً على تنفيذ كود في بيئتك. سيظهر في --allow-scripts-pending، ويمكن لفريقك التحقيق قبل الموافقة.
Tip
شغّل npm approve-scripts --allow-scripts-pending في CI كخطوة منفصلة. أفشل البناء إذا ظهرت أي حزم غير موافق عليها. هذا يكتشف الاعتماديات الجديدة المضافة عبر PRs قبل أن تتمكن من تنفيذ كود.
هذه الفئات عادةً تحتاج موافقة صريحة للعمل بشكل صحيح:
معالجة الصور الأصلية: sharp، canvas، jimp (مع ربط أصلي)، imagemagick
أدوات البناء مع مكونات أصلية: esbuild، swc، node-sass، sass (مع مترجم أصلي)
مشغلات قواعد البيانات: better-sqlite3، sqlite3، pg-native، oracledb
التشفير: argon2، bcrypt، sodium-native
تكامل النظام: fsevents (مراقبة الملفات في macOS)، node-pty، serialport
أدوات Monorepo: الحزم التي تستخدم سكريبتات prepare لاعتماديات git
yaml#.github/workflows/ci.yml - name: Install dependencies run: npm ci - name: Verify native modules run: node scripts/verify-native-modules.js - name: Run tests run: npm test
خطوة التحقق بين التثبيت والاختبار هي ما يمنع موقف "بناء أخضر، تشغيل معطوب". اجعل سكريبت التحقق يستورد ويستخدم فعلياً كل وحدة أصلية يعتمد عليها تطبيقك.
تغييرات أمان التثبيت في npm v12 تأتي مع تحول جذري آخر: رموز الوصول الدقيقة (GATs) التي تتجاوز 2FA يتم إيقافها تدريجياً.
| المرحلة | التاريخ | التأثير |
|---|---|---|
| GATs تفقد قدرات الإدارة الحساسة | أغسطس 2026 | لا يمكن إدارة الحسابات أو الحزم أو المنظمات |
| GATs تفقد قدرة النشر | ~يناير 2027 | يجب استخدام النشر الموثوق |
البديل هو النشر الموثوق عبر OIDC. بدلاً من رموز طويلة الأمد في أسرار CI، يطلب سير العمل بيانات اعتماد قصيرة الأمد وينشر مع شهادات المصدر.
yaml## النشر الموثوق في GitHub Actions jobs: publish: permissions: id-token: write contents: read steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '22' registry-url: 'https://registry.npmjs.org' - run: npm publish --provenance --access public
صلاحية id-token: write تسمح لسير العمل بطلب رمز OIDC. تتحقق npm منه مقابل إعدادات الناشر الموثوق، وتصدر بيانات اعتماد قصيرة الأمد، وتربط بيانات المصدر بالحزمة المنشورة.
لا مزيد من الرموز طويلة الأمد في أسرار المستودع. لا مزيد من عدم اليقين حول ما إذا كان رمز أُنشئ منذ سنوات لا يزال موجوداً في مكان ما.
لماذا هذا مهم: معاً، موافقات سكريبتات التثبيت والنشر الموثوق تنقل npm إلى نموذج أمني مختلف. تنفيذ الكود يحتاج موافقة صريحة. النشر يحتاج دليلاً تشفيرياً أنه جاء من خط CI الصحيح.
npm 11.16+ تشحن هذه السلوكيات خلف تحذيرات، لذا يمكن للفرق البدء الآن دون التحول الكامل لـ npm v12.
bash## تفعيل سلوك npm v12 في npm 11.16+ npm config set allow-scripts false npm config set allow-git none npm config set allow-remote none
شغّل خط CI الكامل مع هذه الإعدادات. انظر ما ينكسر. ابنِ allowScripts. ثم أزل تجاوزات الإعدادات والتزم بتحديثات package.json.
bash## مراجعة الاعتماديات الحالية npm approve-scripts --allow-scripts-pending > scripts-to-review.txt # راجع كل حزمة cat scripts-to-review.txt | while read pkg; do npm view "$pkg" repository.url npm view "$pkg" scripts done
الهدف بسيط: أن يكون allowScripts جاهزاً ومختبراً قبل أن تصبح npm v12 الافتراضية في بيئة CI الخاصة بك. معظم مزودي CI يميلون لتحديث صور Node.js بسرعة بعد إصدار npm رئيسي.
Important
التزم بإعدادات allowScripts في نظام التحكم بالإصدارات. يجب أن تبقى البيئات المحلية وبيئات CI متزامنة، وإلا ستواجه فشل "يعمل على جهازي" في نشر الإنتاج.
ابدأ من هنا
شغّل npm approve-scripts --allow-scripts-pending على مشروعك الرئيسي وابحث عن سكريبتات التثبيت التي لم يراجعها فريقك أبداً.
انتصارات سريعة
غوص عميق
allowScripts لتثبيت الإصدار وتجنب الموافقات الواسعة جداًnpm v12 هي تحول من الثقة الضمنية إلى الموافقة الصريحة. لأكثر من عقد، عمل نظام JavaScript البيئي على افتراض أن مؤلفي الحزم يمكنهم تشغيل كود عشوائي أثناء التثبيت. هذا جعل الكثير من سير العمل المشروعة ممكنة، لكنه أيضاً دعم عالماً يمكن أن تظهر فيه 454,600 حزمة خبيثة في سنة واحدة.
هناك تكلفة حقيقية قصيرة الأمد: بناءات معطوبة، جهد ترحيل، وخطوات CI إضافية. الجانب الإيجابي طويل الأمد: تنفيذ الكود الآن يتطلب قراراً واعياً، وليس فقط npm install.
الفرق التي تبدأ الآن، ببناء قوائم allowScripts وإضافة التحقق من الوحدات الأصلية في CI، عادةً ستنتقل بسلاسة. الفرق التي تنتظر حتى تصل npm v12 لخط الإنتاج هي الأكثر احتمالاً لقضاء أسبوع مؤلم في فك تشابك "كل شيء نجح، لكن لا شيء يعمل".