Transcript
00:00:00إذا قمت بتثبيت حزم NPM، فأنت مستهدف. ربما ليس اليوم، ربما ليس هذا الأسبوع، لكن الأمر
00:00:05قادم بالتأكيد. لقد تعرضت المئات من الحزم للاختراق في الأشهر القليلة الماضية فقط،
00:00:09والأمر لا يتباطأ. لذا بدلاً من القلق في كل مرة يظهر فيها أحد هذه الأمور،
00:00:14قمت بالفعل بتأمين إعداداتي الخاصة عبر NPM و PNPM و BUN، وتبين أن معظم
00:00:18الأشياء التي كانت ستنقذك تستغرق حوالي 30 ثانية للإعداد. لذا في هذا الفيديو،
00:00:23سأطلعك على التغييرات السبعة التي أجريتها، من سطر واحد في التكوين
00:00:27يقتل الهجوم الأكثر شيوعاً مباشرة، إلى أدوات مجانية قدمها المهاجمون أنفسهم
00:00:30ستكتشفهم قبل أن تصل الحزمة حتى إلى جهازك. لنبدأ في ذلك.
00:00:39الأول والأكثر بساطة هو مجرد التوقف عن تنزيل حزم جديدة. معظم هجمات سلسلة
00:00:44التوريد يتم اكتشافها في غضون ساعات، لذا إذا لم تقم بتثبيت إصدارات جديدة تماماً في اللحظة
00:00:48التي يتم طرحها فيها، فإنك تتجنب معظم هجمات سلسلة التوريد هذه تماماً. جميع مديري حزم
00:00:52Node.js الرئيسيين يقدمون الآن شكلاً من أشكال تحديد عمر الإصدار. بالنسبة لـ NPM، تضبط هذا في ملف
00:00:57NPM RC، ويتم ضبطه بالأيام. بالنسبة لـ PNPM، يمكنك ضبطه عالمياً في ملف pnpm-config.yaml،
00:01:03أو يمكنك ضبطه على أساس كل مشروع باستخدام ملف مساحة عمل PNPM، وهذه القيمة يتم ضبطها بالفعل
00:01:08بالدقائق. ومن الجدير بالذكر أيضاً أنه منذ PNPM 11، أصبح هذا لديه افتراضي ليوم واحد،
00:01:14لذا حتى لو لم تقم بضبطه، فلا تزال لديك بعض الحماية. بالنسبة لـ BUN، تضبط هذا في
00:01:17ملف bunfig.toml، إما عالمياً أو مرة أخرى لكل مشروع، ويتم ضبط هذا بالثواني.
00:01:23يدهشني حقاً أنه عبر ثلاثة مديري حزم لنفس الإعداد، توصلنا إلى
00:01:27ثلاث قيم مختلفة، وهو ما يلخص هذا النظام البيئي بشكل جيد. بمجرد ضبط هذا،
00:01:32إذا قمت بعد ذلك بتثبيت حزمة مثل tanstack's react start، يمكنك رؤية أنها لا تثبت
00:01:36الإصدار، بل تثبت الإصدار الأحدث، الذي يتناسب مع معيار عمر الإصدار الخاص بي، والذي بالنسبة لي
00:01:41كان قبل أسبوع واحد. الآن إذا احتجت في أي وقت إلى تجاوز هذا، ربما كانت هناك مشكلة أمنية في
00:01:45الحزمة التي تقوم بتثبيتها، وتحتاج إلى تثبيت أحدث إصدار، فلا يزال بإمكانك القيام بذلك
00:01:49من سطر الأوامر، لكن احذر من النماذج اللغوية الكبيرة (LLMs) أيضاً، حيث رأيت حالات تقوم فيها هذه النماذج
00:01:54باستخدام هذا للتجاوز وتثبيت أحدث الإصدارات على أي حال. شيء آخر يجب مراعاته هو
00:01:59أن MPX و BUNX لا يحترمان هذا الإعداد، فهما لا يزالان يثبتان أحدث إصدار،
00:02:03وهناك طلب سحب (PR) مفتوح في BUN لإصلاح هذا. الآن بينما نحن في هذه الإعدادات، دعنا ننتقل
00:02:07ونوقف تشغيل نصوص التثبيت لـ NPM أيضاً. PNPM و BUN لديهما هذا السلوك افتراضياً،
00:02:12لذا لا يوجد شيء لضبطه لهما. إذا لم تكن تعلم، فعندما تقوم بتثبيت حزمة، يُسمح لهذه الحزمة
00:02:16بالفعل بتشغيل كودها الخاص مباشرة بعد تثبيتها، وقد تم ذلك لحالات استخدام مشروعة
00:02:20مثل تجميع الكود الأصلي (native code) أو تنزيل ملف ثنائي، لكن المشكلة هي أن كل هجوم تقريباً من
00:02:26هجمات سلسلة التوريد استخدم هذه الطريقة لتشغيل كود ضار على جهازك مباشرة بعد التثبيت.
00:02:30إذا وجدت حزمة لديها حاجة مشروعة لأحد هذه النصوص، فلا يزال بإمكانك تمكينه صراحةً.
00:02:34في PNPM، عندما تثبت حزمة تحتوي على نصوص ما بعد التثبيت، فسيخبرك بذلك في الواقع،
00:02:39مثل esbuild هنا، وبعد ذلك يمكنك تشغيل pnpm approved builds لاختيار ما تريد السماح به،
00:02:44وهذا يضبط تكوين pnpm workspace allow builds الخاص بك، ويمكنك أيضاً استخدام
00:02:48علامة allow build في أمر التثبيت للقيام بنفس الشيء. بالنسبة لـ BUN، كما قلت، فإنه يوقف
00:02:52نصوص التثبيت هذه افتراضياً أيضاً، لكن من الجدير بالمعرفة أنه يحتوي بالفعل على قائمة منسقة من
00:02:56الحزم المسموح لها بتشغيل هذه النصوص، ويشمل ذلك الحزم التي قمت بتثبيتها مثل
00:03:00esbuild. يمكنك إلغاء الاشتراك في هذا عن طريق إضافة trusted dependencies إلى package.json الخاص بك،
00:03:04وبهذه الطريقة فقط الحزم التي تسمح بها صراحةً ستكون قادرة على تشغيل نصوص ما بعد التثبيت.
00:03:09يقول أيضاً أنه إذا قمت بضبط المصفوفة على فارغة، فيجب أن يتجاوز ذلك القائمة الافتراضية
00:03:12أيضاً، لكنها لا تعمل على ما يبدو بالنسبة لي، ويبدو أنها خطأ برمجي وجدته على GitHub
00:03:17أيضاً. الحل البديل لهذا في الوقت الحالي هو فقط وضع قيمة واحدة في تلك القائمة، ثم يتم تجاهل القائمة
00:03:21الافتراضية. مع BUN، يمكنك أيضاً تشغيل bun pm untrusted لرؤية الحزم التي تريد تشغيل
00:03:26نصوص ولكنها غير موثوقة بعد، وبعد ذلك يمكنك تشغيل bun pm trust للسماح بواحدة، أو مجرد إضافتها إلى مصفوفة
00:03:30trusted dependencies. يمكنك أيضاً تعطيل النصوص تماماً في BUN عن طريق تعيين install scripts إلى
00:03:35false في ملف bunfig العام الخاص بك. بالنسبة لـ NPM، هذا أصعب قليلاً. بصدق، فقط لا تستخدم
00:03:40NPM، استخدم PNPM، ولكن إذا كان عليك حقاً استخدام NPM لسبب ما، يمكنك الحصول على سلوك قائمة سماح
00:03:45مماثل باستخدام حزمة Lavamote's allow scripts NPM. بهذه الطريقة، تكون مجرد قائمة سماح في
00:03:50package.json الخاص بك أيضاً. النصيحة الثالثة هي حظر التبعيات القائمة على git. مع NPM، يمكن
00:03:55لتبعية أن تُعلن فعلياً كعنوان git url، والذي يتجاوز السجل، ويمكنه حتى شحن ملف NPM RC الخاص به الذي
00:04:01يعيد تمكين نصوص دورة الحياة. هذه في الواقع واحدة من الحيل المستخدمة في هجوم سلسلة توريد NPM
00:04:05الأخير الذي ضرب tan stack. يمكنك إيقاف هذا عن طريق ضبط allow git على none في تكوين NPM الخاص بك،
00:04:10مما يحظرها تماماً، والخيار الآخر هو ضبط هذا على root، والذي يسمح بالفعل بـ git-based
00:04:15التبعات ليتم تثبيتها، ولكن فقط إذا تم الإعلان عنها في root package.json الخاص بك، لذا على الأرجح
00:04:19مضبوطة صراحةً من قبلك. بالنسبة لـ PNPM، هذا الخيار هو block exotic sub-dependencies. عندما يتم ضبط هذا على true،
00:04:25فقط التبعيات المباشرة، أي تلك التي أدرجتها في root package.json الخاص بك، يمكنها استخدام مصادر
00:04:29غريبة مثل مستودعات git أو عناوين URL المباشرة. هذا الخيار غير موجود في Bun حتى الآن، ولكن هناك
00:04:35طلب سحب (PR) مفتوح لإضافة هذا، لذا ربما سنراه قريباً. كمكافأة لإنهاء النصائح التي تتضمن تغييرات
00:04:40التكوين، يحتوي PNPM بالفعل على إعداد trust policy، والذي يمكننا ضبطه على no downgrade، وهذا يعني
00:04:45أن PNPM سيفشل إذا انخفض مستوى ثقة الحزمة مقارنة بإصدارها السابق. لذا إذا كانت الحزمة
00:04:50منشورة سابقاً بواسطة ناشر موثوق، ولكنها الآن لديها فقط دليل على المصدر أو
00:04:55لا يوجد دليل ثقة، فسيفشل التثبيت. يجب أن يساعد هذا في اكتشاف تلك الهجمات التي تجد طرقاً لـ
00:05:00تجاوز عمليات النشر المعتادة. النصيحة رقم أربعة هي على الأرجح الأقوى، وهي
00:05:04استخدام أداة تنظر فعلياً إلى الحزم التي تثبتها ويمكنها تدقيقها قبل أن
00:05:08تلمس جهازك. لهذا، لدينا أداتان قويتان ومجانيتان تماماً. الأولى هي
00:05:14MPQ. يمكنك إعداد هذا عن طريق إنشاء اسم مستعار (alias) لأوامر NPM أو PNPM أو Bun العادية الخاصة بك،
00:05:18بحيث أنه في كل مرة تقوم فيها بتشغيل تثبيت، فإنه يتحقق فعلياً من بعض الأشياء. سوف يبحث عن
00:05:23نقاط الضعف المعروفة مقابل قاعدة بيانات Snyk، ويضع علامة على أي حزمة عمرها أقل من 22 يوماً. سوف
00:05:28يكتشف الـ typo squatting، وهو المكان الذي نشر فيه شخص ما حزمة مثل express بحرف s مكرر، آملاً
00:05:32أن ترتكب خطأ مطبعياً وتثبت تلك بدلاً منها. سيتحقق من توقيع السجل و
00:05:37دليل المصدر. سيحذرك عندما تحتوي حزمة على نصوص ما قبل وما بعد التثبيت، وفوق كل ذلك
00:05:41فهو يتحقق من أشياء أساسية مثل عدد التنزيلات، إذا كان هناك ملف readme، ورخصة، وعنوان URL للمستودع،
00:05:46وما هو البريد الإلكتروني للمسؤول، وما إذا كان هذا النطاق لا يزال مسجلاً. يقوم بكل هذا
00:05:51ثم يقدم لك تقريراً تفاعلياً عن حزمك، حيث لا يزال بإمكانك تحديد ما إذا كنت
00:05:55تريد تثبيتها. الثانية هي socket firewall. هذه في الواقع هي التي أستخدمها،
00:05:59ومرة أخرى، تقوم بإنشاء اسم مستعار لها لكل مديري الحزم المعتادين لديك، وهذه تدعم
00:06:03أشياء خارج JavaScript أيضاً، مثل Python و Rust. مشابه لـ MPQ، عندما تقوم بتشغيل تثبيت مع
00:06:08هذا، فإنه سيتحقق من socket ويحظر أي حزم ضارة مؤكدة من قبل البشر، وسيحذرك أيضاً
00:06:12من أي تهديدات مكتشفة بواسطة الذكاء الاصطناعي، وهي التهديدات التي لم تتم مراجعتها من قبل البشر بعد. لكي أكون صادقاً،
00:06:16لقد اخترت socket firewall بشكل أساسي لأنها الأداة التي سمعت عنها أولاً، لكنني أثق أيضاً في socket لأنهم
00:06:21اكتشفوا الكثير من الحزم الضارة مؤخراً، وحتى أن المهاجمين أجروا مقابلة قالوا فيها
00:06:25إن socket ستكتشف البرامج الضارة قبل أن تصل الحزمة حتى إلى جهازك، وهو إعلان جيد جداً
00:06:30لهم، ويعجبني أيضاً أنها تدعم أكثر من مجرد JavaScript مع UV pip و cargo.
00:06:35إذا قمت بتثبيت أي منهما، فستحتاج إلى التأكد من مسح ذاكرة التخزين المؤقت لمدير الحزم
00:06:38للتأكد فقط من أن كل حزمة مثبتة يتم فحصها بواسطة جدار الحماية. النصيحة الخامسة تتعلق بملفات القفل (lock files) الخاصة بك.
00:06:42ملفات القفل الخاصة بك هي المكان الذي يوجد فيه عنوان التنزيل الفعلي لكل حزمة، والمشكلة هي،
00:06:47لا أحد يراجع ملفات القفل الخاصة به في طلب سحب (PR). لذا إذا قام شخص ما بفتح PR ضد
00:06:51المستودع الخاص بك، فيمكنه تعديل عنوان URL تم حله بهدوء ليشير إلى حزمة يتحكمون فيها، وأيضاً ضبط
00:06:56تجزئة النزاهة المطابقة (matching integrity hash) بحيث لا يبدو أي شيء غير طبيعي. الآن في المرة التالية التي تقوم فيها بتشغيل تثبيت، أنت تسحب
00:07:01الكود من خادم المهاجم. الخبر السار هو، إذا كنت تستخدم PNPM، فأنت غير عرضة
00:07:05لهذا الهجوم. فهو لا يحتفظ بمصادر الجدول تلك التي يمكن تبديلها، كما أنه لن يثبت
00:07:09أي شيء موجود في ملف القفل، ولكن لم يتم الإعلان عنه في package.json الخاص بك. لم أتمكن من العثور على أي
00:07:14معلومات ملموسة عن bun، لذا قد يظل هذا عرضة لهذا. الحل إذا لم تكن
00:07:18تستخدم PNPM هو استخدام أداة تسمى lockfileLint. تقوم بتثبيت هذا كتبعية تطوير، وهي تتحقق من
00:07:23ملف القفل الخاص بك، وتتحقق من حل كل حزمة من مضيف موثوق، مثل سجل NPM. هي تتحقق من
00:07:28عناوين URL المحلولة تطابق اسم الحزمة، وتتحقق أيضاً من أن تجزئات النزاهة حقيقية
00:07:32أيضاً. إذا اشتبهت في أن شيئاً ما قد تم العبث به، فسيفشل التثبيت. النصيحة 6 هي التوقف
00:07:37عن استخدام NPM install في CI والإنتاج، وبدلاً من ذلك استخدم clean install. الأمر لهذا في NPM هو
00:07:42مجرد npm ci، وبالنسبة لـ bun و PNPM، تقوم في الواقع بإضافة علامة frozen lockfile، لكن لديهم أيضاً أوامر
00:07:47CI كاسم مستعار تقوم بنفس الشيء. PNPM يستخدم هذا بالفعل افتراضياً إذا اكتشف أنه
00:07:52يعمل في بيئة CI. أمر التثبيت النظيف يثبت بالضبط ما هو موجود في ملف القفل،
00:07:57لا شيء آخر، وإذا لم يتفق ملف القفل و package.json، فإنه يتوقف فقط ويظهر خطأ،
00:08:01بدلاً من التخمين والتثبيت على أي حال. لذا يجب أن يمنع هذا مهاجماً من تسريب
00:08:05إصدار متبادل. لا شيء من هذا يعمل إذا لم تكن تقوم بـ commit لملف القفل الخاص بك في المقام
00:08:09الأول، لذا تأكد من وجود ذلك في التحكم في الإصدار وليس في gitignore الخاص بك، وسأعترف عندما
00:08:13بدأت لأول مرة في تعلم البرمجة كطفل، اعتقدت أنك من المفترض أن تتجاهل هذه، لذا أنا سعيد
00:08:17لأنني تعلمت القيام بـ commit لها. لذا تلك النصائح الست كانت في الغالب تكويناً وأدوات، ولكن هناك أيضاً بعض
00:08:21العادات التي يمكنك تبنيها لمساعدتك على تجنب الهجمات. الأولى هي التوقف عن التحديث الأعمى
00:08:25لكل شيء. ربما قمت بتشغيل npm update أو إصدارات أخرى من هذا الأمر من قبل، وقممت فقط
00:08:30بتحديث كل تبعية إلى أحدث إصدار لها دفعة واحدة، لكن هذا هو نوع السلوك الدقيق الذي يأمل فيه هؤلاء
00:08:35المهاجمون، لذا اذهب بالفعل من خلال هذه الترقيات واسأل نفسك لماذا تحتاج إلى
00:08:39ترقيتها. العادة الثانية تصبح أكثر صلة، فقط استخدم عدداً أقل من الحزم. كل
00:08:43تبعية تضيفها هي سطح هجوم آخر، ومعظم هذه الهجمات تنتشر من خلال تبعيات
00:08:48تبعية، لذا من الجدير حقاً التساؤل لماذا تحتاج إلى تلك المكتبة. بعض الأمثلة الشائعة التي أراها لـ
00:08:53هذا هي أشياء مثل Lodash للوظائف التي يمكن القيام بها بمقتطف صغير من الكود، أو Axios عندما
00:08:58fetch يمكن أن تفعل نفس الشيء. السبب الذي أقوله أن هذا أصبح أكثر صلة هو في عصر
00:09:03البرمجة الوكيلية (agentic coding)، من السهل جداً جعل الذكاء الاصطناعي يكتب بضع وظائف لك بدلاً من استخدام تبعية.
00:09:08العادة الثالثة هي تثبيت التبعيات على إصدار محدد، لذا فإن الترقية هي دائماً خيار متعمد
00:09:12، ولكن فقط اعلم أن هذا يقفل فقط الحزم التي تختارها في package.json الخاص بك،
00:09:17ويمكن لتبعات تبعياتك أن تستمر في استخدام نطاقاتها الخاصة، وهو بالضبط سبب أهمية
00:09:21فترة التبريد من النصيحة 1. كل هذه مجتمعة يجب أن تمنحك بعض راحة البال بأنك لن
00:09:25تثبت حزمة مخترقة عن طريق الخطأ. إنها ليست لا تقهر، لكنها أفضل بكثير من
00:09:29لا شيء. النصيحة النهائية هي فقط تشغيل كل شيء في حاوية تطوير (dev container) صلبة، لكنني وجدت دائماً
00:09:34أن ذلك يمثل بعض المتاعب، لذا ينتهي بي الأمر بالعودة إلى التطوير المحلي. إذا كنت تعرف أي طريقة أخرى
00:09:38لحماية نفسك من هذا النوع من الهجمات، فأخبرني في التعليقات أدناه، بينما أنت هناك
00:09:42اشترك، وكما هو الحال دائماً أراك في المرة القادمة.
Community Posts
No posts yet. Be the first to write about this video!
Write about this video