ثغرة في LuaRocks.org سمحت بتنفيذ أوامر على الخادم شهرًا ونصفًا رغم وجود sandbox مكتوب بعناية
الحماية حصرت الأسماء التي يستطيع الكود الوصول إليها، لكن المدخل الذي لم يُتوقع لا يحتاج إلى أسماء. السؤال في أي بيئة معزولة هو ما يقبله المحمّل، لا ما أُغلق.
نشر مستودع حزم لغة Lua، LuaRocks.org، بيانًا رسميًا عن ثغرة ظلت نحو شهر ونصف تسمح لأي مستخدم مسجّل بتنفيذ أوامر على خادم الموقع. وأُبلغ عن الثغرة يوم 25 سبتمبر 2026 عبر CISA، وأُصلحت يوم 26 سبتمبر.
وأصل المشكلة أن ملف وصف الحزمة، الـ rockspec، هو نفسه ملف Lua. ولذلك كان الموقع يشغّله لقراءة اسم الحزمة ورقم نسختها. ولتشغيله بأمان اتخذ ثلاثة احتياطات تبدو صحيحة: تحميله بدالة loadstring، وتشغيله في بيئة فارغة عبر setfenv حتى لا يصل إلى أي متغيرات عامة، ووضع حد أقصى لعدد التعليمات.
ولم تكن الثغرة في أي من الثلاثة. فدالة loadstring في Lua 5.1 وLuaJIT تقبل افتراضيًا نوعين من المدخلات: الكود المصدري، والـ bytecode المترجم مسبقًا، ولم يكن الكود يقيّدها بالنص وحده. كما أن LuaJIT لا يتحقق من سلامة الـ bytecode أصلًا، فتمكّن ملف معدّ عمدًا من الخروج من حدوده والوصول إلى الدوال التي كان الـ sandbox يخفيها.
والخلاصة أن البيئة الفارغة تتحكم في الأسماء التي يستطيع الكود البحث عنها، بينما لا يحتاج هذا النوع من المدخلات إلى البحث عن أسماء.
واستُغلت الثغرة فعلًا بحسب البيان. فقد نُفّذت أوامر على الخادم يوم 9 يوليو، ثم يوم 7 أغسطس مع نشر 3 حزم خبيثة، إحداها باسم bcrcewon، ثم جرت مئات المحاولات الآلية يومي 16 و20 أغسطس.
وتمثّل الإصلاح في تشغيل الملفات بوضع يقبل النص فقط، ورفض أي ملف يبدأ بالبايت 27 الذي يميّز الـ bytecode، وطُبّق ذلك أيضًا على ملفات manifest القادمة من خوادم أخرى.
والدرس يتجاوز Lua. فكل نظام يستقبل مدخلات من المستخدمين ويشغّلها في بيئة “محدودة” يواجه السؤال نفسه: ما الذي يقبله المحمّل غير الصيغة المتوقعة؟ والسؤال ذاته يُطرح على eval، وعلى عمليات deserialization، وعلى أي أداة تقرأ ملفًا بصيغة يُفترض أنها معروفة.