نود.js يرقّع 10 ثغرات، أربع في نموذج الأذونات

في 29 يوليو 2026 أصدر فريق نود.js ثلاث نسخ أمنية في وقت واحد: 22.23.2 و24.18.1 و26.5.1، تُغلق معها عشر ثغرات مسجّلة (CVE) على كل خطوط الإصدار المدعومة. الرقم لافت، لكن الأهم من الرقم هو توزيعه: أربع من العشر تقع داخل نموذج الأذونات — الميزة نفسها التي يعتمد عليها كثير من الفرق لتقييد ما تقدر عليه العملية الواحدة.

المشكلة: نتعامل مع الأذونات كأنها صندوق رملي

نموذج الأذونات دخل نود.js في الإصدار 20، وفكرته بسيطة وجذّابة: شغّل العملية بـ --permission وحدّد ما تحتاجه فقط — قراءة من مجلد، كتابة في آخر، ولا شبكة ولا عمليات فرعية. مع انتشار سكربتات البناء وأدوات الـ CLI وحِزم postinstall، بدا الخيار وكأنه الحل: احبس العملية في مجلدها وانتهى الأمر.

توثيق نود.js نفسه كان أوضح من ذلك دائمًا. النموذج موصوف حرفيًا كـ«حزام أمان» للكود الموثوق، لا كحاجز أمني ضد كود خبيث — لأن نود.js يثق في أي كود يُطلب منه تشغيله. الفارق بين «يمنع الخطأ غير المقصود» و«يوقف مهاجمًا» فارق كبير، وهذه الرقعة تُظهره على أرض الواقع.

ما تغيّر

الثغرة الأبرز في هذه المجموعة هي CVE-2026-58043 بتصنيف High. ملخّصها: عملية مُنحت صلاحية القراءة أو الكتابة في مجلد واحد تستطيع استغلال طريقة مطابقة البادئات في شجرة الـ radix المستخدمة داخليًا، لتقرأ أو تكتب خارج القائمة المسموح بها. أي أن --allow-fs-read=/srv/app/data لم يكن يعني ما يبدو أنه يعنيه.

ومعها ثغرتان أخف — CVE-2026-56847 وCVE-2026-58039 — تسمحان لأحداث التتبّع (trace events) وتقارير التشخيص بكتابة مخرجاتها في مسارات عشوائية على القرص، أي تجاوز آخر للقائمة المسموح بها لكن من باب المخرجات لا المدخلات.

وخارج الأذونات، الجانب الأخطر عمليًا هو HTTP/2. CVE-2026-56848 هي استخدام بعد التحرير (heap use-after-free) في nghttp2_session_mem_send()، ويُفتح الباب فيها لتنفيذ كود عن بُعد عبر نداءات متداخلة أثناء معالجة الرسائل. وعلى خطّي 22.x و24.x تُضاف CVE-2026-56846، حيث تتجاوز كتل الترويسات حدود الذاكرة المقرّرة فتُستنزف ذاكرة الجلسة. الباقي متوسط أو منخفض ويشمل https وsqlite وdns وzlib وhttp، مع تحديث llhttp إلى 9.4.3 وundici إلى 8.9.0.

مثال عملي: لا تجعل العلَم هو خط الدفاع الوحيد

الترقية إلزامية، لكن الدرس المعماري يبقى بعد أن تُنسى الرقعة نفسها. القاعدة العامة: أي ضمان أمني يعتمد على طبقة واحدة هو ضمان مؤقّت. فإذا كان مجلد البيانات هو الحد الذي لا يجوز تجاوزه، فليكن هذا الحد مكتوبًا في كود التطبيق أيضًا، لا في سطر التشغيل فقط. ثم اسأل نموذج الأذونات بدل أن تفترض ما منحه لك.

js
// docs.js
import { readFile } from 'node:fs/promises';
import { resolve } from 'node:path';

const ROOT = '/srv/app/data';

// طبقة أولى: تحقّق صريح من أن المسار داخل الجذر
function safePath(userInput) {
  const target = resolve(ROOT, userInput);
  if (target !== ROOT && !target.startsWith(ROOT + '/')) {
    throw new Error('path escapes data root');
  }
  return target;
}

export async function readDoc(name) {
  const path = safePath(name);

  // طبقة ثانية: اسأل نموذج الأذونات بدل الافتراض
  if (!process.permission.has('fs.read', path)) {
    throw new Error(`fs.read not granted: ${path}`);
  }

  return readFile(path, 'utf8');
}

وللتشغيل، مع منح أضيق نطاق ممكن بدل الاعتماد على القائمة وحدها:

bash
node --permission --allow-fs-read=/srv/app/data ./server.js

# وتأكّد من النسخة أولًا
node -p "process.versions.node"
# 22.x ← 22.23.2   |   24.x ← 24.18.1   |   26.x ← 26.5.1

تحفّظات من الواقع

  • الإصدارات المنتهية الدعم (EOL) مصابة أيضًا ولن تُرقّع. إن كنت على 20.x أو أقدم، الترقية هي الخيار الوحيد.
  • ثغرات HTTP/2 تخصّ من يشغّل http2 مباشرة، ومن يعمل خلف بروكسي يمرّر HTTP/2 حتى الأصل — راجع طبقة الحواف قبل أن تطمئن.
  • process.permission.has() يفيد كتحقّق دفاعي، لكنه ليس بديلًا عن التحقق من المدخلات. الطبقتان معًا، لا إحداهما.
  • هذه ثاني موجة رقع كبيرة في الأسبوع نفسه بعد إصدار Next.js الأمني — يستحسن التعامل معهما كنافذة صيانة واحدة.

الخلاصة

رقّع الآن: 22.23.2 أو 24.18.1 أو 26.5.1 حسب خطّك. وبعد الترقية، أعد النظر في الموضع الذي أسندت فيه ضمانات أمنية إلى --permission. الميزة مفيدة وستتحسّن، لكنها موصوفة كحزام أمان لسبب — والبنية التي تعتمد على طبقتين مستقلتين تبقى واقفة عندما تسقط إحداهما.

المصدر الرسمي: Node.js — Wednesday, July 29, 2026 Security Releases

نود.js يرقّع 10 ثغرات، أربع في نموذج الأذونات · bahashwan.dev