دليل عملي

ثغرة Node.js CVE-2026-111497 (Brotli): التحديث إلى 22.23.4

الأمان والمراقبة10 دقائق للقراءةعدد الخطوات: 12

في 21 أكتوبر 2026، أصدر Node.js النسخ 22.23.4 و24.22.1 و26.12.1 لإصلاح CVE-2026-111497، وهي كتابة خارج الحدود في مفكك Brotli قد تصل إلى تنفيذ تعليمات برمجية عن بُعد. على مجموعة مواقع تعمل بـ Next أو Nuxt أو Express، لا يكفي «حدّث» جوابًا: عليك أن تعرف أي التطبيقات تفكّ فعلًا ضغط Brotli غير الموثوق، وأي العمليات ما زالت تعمل بالملف التنفيذي القديم، وماذا تفعل بتطبيق عالق على Node 20. يقدّم هذا الدليل الأوامر اللازمة للجرد والإصلاح والتحقق، ثم لتقليل الخطر حين يتأخر الإصلاح.

المحتويات· ما الذي يصلحه إصدار Node.js في أكتوبر 20261/12
  1. 01ما الذي يصلحه إصدار Node.js في أكتوبر 2026
  2. 02الإصدارات المتأثرة والإصدارات المصلَحة
  3. 03هل أنت مكشوف: المعيار الحاسم
  4. 04من أين يدخل Brotli غير الموثوق إلى تطبيق Node
  5. 05جرد المجموعة في خمس عشرة دقيقة
  6. 06بأي ترتيب تعالج المجموعة
  7. 07التحديث بحسب طريقة التثبيت
  8. 08العملية الجارية تحتفظ بـ Node القديم
  9. 09إذا تعذّر التحديث اليوم
  10. 10لا تُصلح ثغرة Brotli وحدها
  11. 11لوكالة: إصلاح واحد لكل فرع لا لكل موقع
  12. 12الوثائق الرسمية

ما الذي يصلحه إصدار Node.js في أكتوبر 2026

نشر Node.js في 21 أكتوبر 2026 تحديثات للفروع 22 و24 و26. ومن بين الثغرات العشر المُصلَحة، يصنّف المشروع CVE-2026-111497 بدرجة High: يكتب مفكك Brotli المدمج خارج حدود مخزن مؤقت داخلي عندما يتلقى بيانات مشوّهة. وعمليًا، كان تبديل كتلة غير صالح يُبلَّغ عنه كحاجة مؤقتة إلى مزيد من المدخلات بدل أن يكون خطأ نهائيًا في الصيغة، فيواصل المفكك العامل بالتدفق إضافة البايتات إلى مخزن داخلي من ثمانية بايتات. وتتراوح العواقب المحتملة بين انهيار العملية وكشف محتوى الذاكرة وتنفيذ تعليمات برمجية عن بُعد بصلاحيات عملية Node.

أما الخطورة فلها قراءتان. يقول Node.js إنها High؛ وتمنحها Google، بصفتها جهة ترقيم الثغرات، درجة CVSS v4 قدرها 9.2 بحسب تحليل Rapid7. وحتى 26 أكتوبر 2026، لا تعلم Rapid7 بأي استغلال فعلي، والثغرة غير مدرجة في كتالوج CISA للثغرات المستغَلة. فالثغرة إذن غير مستغَلة حتى الآن بحسب Rapid7: إنها فرصة للتحديث بهدوء، لا سببًا للانتظار.

الإصدارات المتأثرة والإصدارات المصلَحة

مرّر الجدول أفقيًا

الحالةالوضعالإجراء
Node.js 22.xمتأثر قبل 22.23.4الانتقال إلى 22.23.4
Node.js 24.xمتأثر قبل 24.22.1الانتقال إلى 24.22.1
Node.js 26.xمتأثر قبل 26.12.1الانتقال إلى 26.12.1
Node.js 20.x وسائر الفروع المنتهية الدعمتُعامَل كمتأثرة، ولا إصلاح لهاالترحيل إلى 22.x أو 24.x
صورة Docker من نوع node:<الفرع>متأثرة إلى أن تُعاد بناء الصورةإعادة البناء بالخيارين --pull --no-cache
ملف Node تنفيذي مضمَّن في أداة (Electron، ملف تنفيذي مُجمَّع)يتوقف على النسخة المضمَّنةتحديث الأداة نفسها
برنامج آخر يضمّن مفكك Brotli نفسهبحسب الجهة المطوّرةقراءة نشرتها الخاصة

هل أنت مكشوف: المعيار الحاسم

لا يكفي أن يكون Node المثبَّت ضعيفًا حتى يصبح قابلًا للاستهداف. تستهدف نشرة Node.js تطبيقًا يفكّ بـ node:zlib بيانات Brotli يقدّمها مهاجم، عبر zlib.createBrotliDecompress أو zlib.brotliDecompress. وتوضح Rapid7 أن مجرد وجود المفكك لا يثبت التعرّض: كل شيء يتوقف على ما يفكّه التطبيق. لكن لا تستنتج سريعًا غياب الخطر، فكثيرًا ما يمرّ Brotli عبر مكتبات لم تكتبها.

الربط برأس Content-Encoding: br قراءتنا نحن، وليس تأكيدًا من النشرة. ففي الشيفرة المصدرية العامة، يفكّ fetch المدمج في Node (undici) استجابات br بـ zlib.createBrotliDecompress، ويتضمن محوّل HTTP في axios فك الترميز نفسه، وتفعل شيفرة body-parser الحالية الأمر ذاته لأجسام الطلبات الواردة. فثمة تدفقان يجب فحصهما: ما يتلقاه تطبيقك من العملاء، وما يجلبه من خوادم الأطراف الثالثة. يمكنك التحقق من ذلك في شجرة اعتمادياتك بأوامر الجرد أدناه.

من أين يدخل Brotli غير الموثوق إلى تطبيق Node

  • طلبات واردة مضغوطة — واجهة Express أو خادم مخصص يستخدم body-parser يفكّ جسمًا Content-Encoding: br أرسله أي عميل.
  • استجابات خدمات الأطراف الثالثة — fetch أو axios يستدعي واجهة برمجية أو موجز RSS أو webhook أو صفحة للمعاينة: الخادم البعيد هو من يختار ترميز الاستجابة.
  • العرض من جهة الخادم — تطبيق Next أو Nuxt يجلب بيانات بعيدة أثناء العرض يمرّ بهذه الاستدعاءات الصادرة نفسها.
  • وسطاء وبوابات مكتوبة بـ Node — مكوّن يفكّ الضغط لفحص المحتوى أو تحويله أثناء مروره يفتح التدفقين معًا.
  • معالجة الملفات — خدمة تقبل ملفات أو أرشيفات مضغوطة بـ Brotli وتفتحها بـ zlib.brotliDecompress.
  • أدوات البناء والتكامل المستمر — سكربتات النشر والمهام التي تنزّل ملفات ناتجة: أقل تعرّضًا، لكنها تستخدم الملف التنفيذي نفسه وتُحدَّث في الوقت نفسه.
  • لا مسار محدَّدًا — أولوية أدنى لا معدومة: يكفي اعتماد يُضاف لاحقًا لإنشاء التعرّض، كما يصلح الإصدار ثغرات أخرى.

جرد المجموعة في خمس عشرة دقيقة

  1. قراءة النسخة على كل جهاز

    node -v
    which -a node
    كثيرًا ما تتعايش عدة ملفات تنفيذية: ملف النظام، وملف nvm، وملف داخل حاوية. يسردها which -a جميعًا، وليس الأول دائمًا هو ما تستخدمه الخدمة.

  2. العثور على الملف التنفيذي الفعلي لكل عملية

    ps -eo pid,user,args | grep -E '[n]ode|[p]m2'
    sudo readlink -f /proc/<pid>/exe
    يعطي الأمر الثاني، بعد تمرير رقم العملية الذي وجدته، المسار الدقيق للملف الذي يشغّل العملية. وهو الجواب الموثوق الوحيد على جهاز يحمل عدة تثبيتات لـ Node.

  3. استجواب الحاويات

    docker ps
    docker exec <conteneur> node -v
    docker images | grep node
    الحاوية العاملة لا تُصلح نفسها: تحتفظ بالصورة التي بدأت بها، حتى لو وُجدت صورة أحدث على الجهاز.

  4. البحث عن الاستدعاءات المباشرة في شيفرتك

    grep -rEn "createBrotliDecompress|brotliDecompress" --include=*.js --include=*.mjs --include=*.ts . --exclude-dir=node_modules
    كل سطر يظهر هو نقطة تفكّ فيها شيفرتك ضغط Brotli. انظر من أين تأتي البيانات: ملف أنتجته بنفسك لا يحمل الخطر ذاته الذي يحمله جسم طلب.

  5. البحث عن المكتبات التي تفكّ الضغط نيابة عنك

    grep -rlE "createBrotliDecompress" node_modules --include=*.js
    npm ls body-parser axios undici
    يسرد الأمر الأول الحزم المثبَّتة التي تستدعي المفكك؛ ويُظهر الثاني نسخ body-parser وaxios وundici الموجودة في المشروع. شغّلهما في كل مستودع، لا في الأحدث فقط.

  6. رصد الملفات التنفيذية المُجمَّعة

    الأدوات التي تحمل Node خاصًا بها (تطبيقات Electron، الملفات التنفيذية المُجمَّعة) لا يغطيها apt. ابحث عن نسختها في وثائقها وتحقق مما إذا أصدرت الجهة المطوّرة نسخة مصلَحة.

  7. تدوين النتيجة في جدول

    سطر لكل عملية: الجهاز، العميل، فرع Node، النسخة، هل حُدِّد مسار Brotli أم لا. يحدد هذا الجدول ترتيب المعالجة، وسيكون دليلًا بعد إتمام التحديث.

بأي ترتيب تعالج المجموعة

مجموعة مواقع العملاء، بنسخها وتثبيتاتها المتباينة، لا تُحدَّث بحركة واحدة، ولا حاجة إلى ذلك. ابدأ بالخوادم المكشوفة على الإنترنت التي تتلقى أجسامًا مضغوطة أو تستدعي خدمات أطراف ثالثة: العرض من جهة الخادم، والبوابات، والوسطاء، والواجهات البرمجية العامة. ثم التطبيقات الداخلية والعمال، ثم أدوات البناء. أما التطبيقات على Node 20 فحالة منفصلة: لن يوجد لها إصلاح أبدًا، والمخرج الوحيد هو الترحيل إلى 22.x أو 24.x، وهو أمر يُخطَّط مع العميل بدل ارتجاله. تقدّم على دفعات من بضعة أجهزة، وتحقق من كل دفعة قبل الانتقال إلى التالية.

التحديث بحسب طريقة التثبيت

  1. حزمة apt (مستودع NodeSource أو التوزيعة)

    apt-cache policy nodejs
    sudo apt-get update
    sudo apt-get install --only-upgrade nodejs
    node -v
    اقرأ أولًا المصدر الذي يعرضه apt-cache policy: يجب أن يشير المستودع إلى الفرع الصحيح (node_22.x أو node_24.x). مستودع بقي على فرع منتهي الدعم لن يعرض الإصلاح أبدًا. وقد تحمل حزمة التوزيعة رقمًا مختلفًا: قارنه بنشرة توزيعتك.

  2. nvm

    nvm install --reinstall-packages-from=current 22
    nvm alias default 22
    nvm use 22
    node -v
    يثبّت الأمر أحدث نسخة 22.x متاحة؛ تحقق من أن node -v يعرض 22.23.4 أو أحدث. افعل الشيء نفسه مع 24 إن كان هذا فرعك. الخدمات التي يشغّلها مستخدم آخر لها nvm خاص بها.

  3. Docker

    غيّر الوسم في سطر FROM، مثل FROM node:22 أو FROM node:24 مع النوع الذي تستخدمه أصلًا، ثم:
    docker build --pull --no-cache -t monapp:corrige .
    docker compose up -d
    يجلب الخيار --pull أحدث صورة أساس، ويمنع --no-cache إعادة استخدام طبقة بُنيت بـ Node القديم. لا تُستبدل الحاوية العاملة إلا عند إعادة النشر.

  4. pm2

    pm2 restart all
    pm2 update
    بعد استبدال الملف التنفيذي، يعيد pm2 restart تشغيل التطبيقات؛ ويحدّث pm2 update خدمة pm2 الموجودة في الذاكرة. وتضيف وثائق pm2 أنه بعد ترقية Node ينبغي تحديث سكربت الإقلاع أيضًا:
    pm2 unstartup
    pm2 startup
    pm2 save

  5. خدمة systemd أو مشرف آخر

    sudo systemctl restart <service>
    أعد تشغيل كل خدمة على حدة، وراجع سجلها ومسار الصحة فيها قبل الانتقال إلى التالية. وفي تطبيق خلف موزّع أحمال، أخرج الجهاز من المجموعة طوال مدة إعادة التشغيل.

العملية الجارية تحتفظ بـ Node القديم

استبدال الملف التنفيذي لا يصلح العمليات الجارية: فهي تحتفظ بالنسخة القديمة في الذاكرة حتى تُعاد. وإظهار node -v نسخة صحيحة على الجهاز لا يثبت شيئًا عن خدمة بدأت أمس. بعد كل إعادة تشغيل، تحقق من العملية نفسها: pm2 jlist أو pm2 show <nom> لمعرفة نسخة Node المستخدمة، أو اعرض process.version في مسار الصحة لديك.

إذا تعذّر التحديث اليوم

لم ينشر Node.js أي حل بديل: التخفيف الوحيد من الجهة المطوّرة هو النسخة المصلَحة. وعند تعذّر ذلك توصي Rapid7 بتقييد مسارات التطبيق التي تفكّ ضغط Brotli غير الموثوق أو تعطيلها. وهذا ما يعنيه عمليًا. النقاط التالية إجراءات لتقليل الخطر نقترحها نحن، وليست توصيات من الجهة المطوّرة، ولا يحلّ أي منها محل الإصلاح.

في الطلبات الواردة، ارفض Brotli عند الوسيط العكسي، مثلًا في nginx: if ($http_content_encoding ~* br) { return 415; }. اختبر بـ nginx -t قبل إعادة التحميل، وتحقق من أن أيًا من عملائك الشرعيين لا يرسل أجسامًا بترميز br. وفي استجابات الأطراف الثالثة، أعلن الترميزات المفيدة فقط عبر الرأس Accept-Encoding: gzip، وقيّد الوجهات المسموح بها لاستدعاءاتك الصادرة. وهذا الإجراء الأخير جزئي: يستطيع خادم خبيث الرد بترميز br حتى لو لم يُطلب، ويتبع المفكك رأس الاستجابة. وعلى Vercel، تحجب قواعد WAF التدفق الوارد لكنها لا تحجب الاستجابات التي تجلبها دوالك؛ ويظل إعادة النشر بنسخة مصلَحة ضروريًا.

لا تُصلح ثغرة Brotli وحدها

يصلح الإصدار نفسه تسع ثغرات أخرى. منها ثغرتان عاليتا الخطورة تتجاوزان التحقق من اسم المضيف في TLS، هما CVE-2026-105483 وCVE-2026-106069، إضافة إلى CVE-2026-105482، وهي اقتطاع أسماء المضيفين التي تحوي محرف NUL في تحليلات DNS، ومصنفة High أيضًا. ولا تمسّ كلها الفروع نفسها: تخص CVE-2026-105483 الفرعين 26.x و24.x، وتخص الأخريان 22.x كذلك. فلدى تطبيق يتحقق من شهادات TLS في استدعاءاته الصادرة أسباب وجيهة للانتقال إلى النسخة المصلَحة دون انتظار حسم مسألة Brotli.

لوكالة: إصلاح واحد لكل فرع لا لكل موقع

حين تدير عشرات المواقع، يستغرق أمر التحديث دقيقة واحدة؛ أما الوقت فيضيع في مكان آخر. عليك أن تعرف أي جهاز يشغّل أي نسخة لدى أي عميل، ثم تحصل على موعد لإعادة التشغيل. احتفظ إذن بسجل حي يغذّيه الجرد أعلاه: عند الثغرة التالية، يعطيك مجرد تصفية على فرع Node قائمة المواقع الواجب معالجتها. وكلما قلّت الصيغ المختلفة في المجموعة قلّت الحالات التي تُعالج يدويًا، واستضافة الموزّعين تلبّي هذا المنطق: واجهة واحدة للمحفظة وتجديدات مجمَّعة، بدل مجموعة خوادم متفرقة تضاعف الحسابات الواجب متابعتها. أما التطبيقات العالقة على Node 20 فتحتاج معالجة منفصلة: دليل الترحيل المرتبط أسفل هذا المقال يجنّبك اكتشاف غياب الإصلاح يوم الثغرة التالية.

الوثائق الرسمية

نشرة Node.js الأمنية لشهر أكتوبر 2026: https://nodejs.org/en/blog/vulnerability/october-2026-security-releases

تحليل Rapid7 لـ CVE-2026-111497: https://www.rapid7.com/blog/post/etr-cve-2026-111497-critical-out-of-bounds-write-in-the-node-js-brotli-decoder/

نشرة Vercel: https://vercel.com/kb/bulletin/node-js-security-advisory

وثائق وحدة zlib: https://nodejs.org/api/zlib.html

وثائق nvm: https://github.com/nvm-sh/nvm

تحديث pm2: https://pm2.keymetrics.io/docs/usage/update-pm2/

خيارات docker build: https://docs.docker.com/reference/cli/docker/buildx/build/

مجموعة مواقع للتحديث، دون قضاء الليل في ذلك

تُدار محفظة المواقع بصورة أفضل من مكان واحد. مع استضافة الموزّعين من ServOrbit.com، تتابع الحسابات والتجديدات في واجهة واحدة، دون مضاعفة الخوادم الواجب مراقبتها.

بحاجة إلى مساعدة؟

تصفّح مركز المساعدة والأسئلة الشائعة، أو تواصل مع فريقنا — معاودة اتصال أو WhatsApp أو بريد إلكتروني. الدعم بـالعربية والفرنسية والإنجليزية.

راسلنا على WhatsAppيُفتح في علامة تبويب جديدة