ثغرة Next.js CVE-2026-27979: الـ PPR بيفضّي الذاكرة، تتصرف إزاي
لو بتشغّل Next.js بين 16.0.1 و 16.1.6 مع Partial Prerendering، السيرفر بتاعك ممكن يقع من طلب POST واحد. ثغرة CVE-2026-27979 بتخلي الذاكرة تـ grow من غير حد لحد ما الـ process يموت بـ OOM. الإصلاح بياخد أقل من ساعة، بس لازم يتعمل النهارده مش بكرة.
المشكلة باختصار
Vercel أعلنت في منتصف أبريل 2026 عن ثغرة Denial of Service بتصيب الإصدارات من 16.0.1 لحد 16.1.6. الثغرة في الـ Partial Prerendering (PPR) اللي Next.js بتدفعها كـ feature أساسية من Next 16. المهاجم بيبعت طلب POST فيه header اسمه next-resume: 1 مع body كبير، والسيرفر بيـ buffer الطلب كامل في الذاكرة من غير ما يطبّق حد maxPostponedStateSize. كام طلب متوازي = الـ instance راح.
ليه ده بيحصل أصلًا
فكرة الـ PPR إن الصفحة فيها shell ثابت + أجزاء ديناميكية بتتبني على الـ fly. لما الـ client بيطلب استكمال جزء ديناميكي، بيبعت طلب ومعاه state مشفّر علشان السيرفر يكمّل الرندر من نفس النقطة. Next.js عندها إعداد اسمه maxPostponedStateSize مفروض يرفض أي state أكبر من الحد. المشكلة إن المسار اللي بيستقبل next-resume: 1 ما بيتحقّقش من الحد ده قبل ما يبدأ يخزّن الطلب.
النتيجة بالظبط: body بـ 500 ميجا بيتحطّ في الذاكرة قبل ما يتفحص. الـ CWE هنا 770 — Allocation of Resources Without Limits. تصنيف الـ CVSS بيحطها كـ DoS عن بُعد من غير authentication، وده اللي بيخلّيها خطرة حتى لو التطبيق بتاعك مش banking.
الحل الرسمي في 4 خطوات
- افتح
package.jsonواتأكد من إصدارnext. أي رقم من 16.0.1 لـ 16.1.6 = مكشوف. - رقّي لـ 16.1.7 أو أحدث:
npm install next@^16.1.7(أوpnpm update next). - نفّذ
npm run buildمحليًا وشغّل الـ integration tests قبل ما تـ deploy. - بعد الـ deploy، ابعت طلب الاختبار اللي تحت علشان تتأكد إن الثغرة قفلت فعلًا.
# اختبار بعد الترقية — المفروض يرجع 413 أو 400، مش 200 ولا timeout
curl -X POST https://your-app.com/any-ppr-route \
-H "next-resume: 1" \
-H "Content-Type: text/plain" \
--data-binary @<(head -c 50M /dev/urandom)
# راقب الـ memory في نفس اللحظة
ps -o pid,rss,cmd -C nodeلو مقدرش ترقّي فورًا
الحل المؤقت: امنع الـ header عند الـ edge قبل ما يوصل للتطبيق. لو عندك Cloudflare، اعمل WAF rule:
Expression:
(http.request.headers["next-resume"] contains "1") and (http.request.method eq "POST")
Action: Blockلو Nginx قدام التطبيق:
location / {
if ($http_next_resume = "1") {
return 403;
}
proxy_pass http://nextjs_upstream;
}الـ trade-off هنا بالظبط: أي جزء PPR ديناميكي في تطبيقك بيعتمد على الـ header ده هيتعطل. لو الـ route ده admin dashboard أو authenticated، الأغلب مش هتلاحظ فرق. لو landing page عامة فيها PPR شغّال، الـ hydration للأجزاء الديناميكية هتتكسّر. الـ WAF block ده مُفترض يستمر ساعات، مش أيام — رقّي بجد في أقرب deploy window.
ازاي تقيس لو تطبيقك اتعرض للهجوم
لو عندك logs لكل طلب، فلتر على الـ header:
grep -c 'next-resume: 1' /var/log/nginx/access.log
# أو من ELK/CloudWatch — دور على:
# headers.next-resume = "1" AND method = "POST" AND body_size > 1MBطلب PPR شرعي واحد لكل navigation من الـ client. لو لقيت آلاف الطلبات من نفس IP في دقيقة = محاولة استغلال واضحة. راقب الـ memory في نفس الفترة — لو الـ instance اتعملّه restart بسبب OOM killer، ده تأكيد إن الهجوم نجح فعلًا.
الافتراضات والـ trade-offs
الشرح ده مبني على إن التطبيق على Node.js runtime عادي (مش Edge). لو مشغّل على Cloudflare Workers أو Vercel Edge Functions بـ output: 'standalone' + minimal config، Vercel بتقول الإعدادات دي مش متأثرة بنفس القوة. ده ما يعنيش ما ترقّيش — يعني الـ blast radius أقل.
الترقية من 16.1.6 لـ 16.1.7 patch release، المفروض ما تكسرش حاجة. في المشاريع الكبيرة مع custom server logic، ممكن تلاقي edge cases في الـ streaming response handling. لو عندك e2e tests بتتعامل مع PPR routes، شغّلها قبل الـ deploy.
متى لا تحتاج تتصرف دلوقتي
لو أي شرط من دول منطبق، الثغرة مش بتأثّر عليك فعليًا:
- الـ app على Next.js 15 أو أقل — الـ PPR ما كانش شغّال بنفس المسار ده.
- بتستخدم Pages Router بس، من غير App Router أو PPR.
- الـ PPR معطّل صراحةً في
next.config.js:experimental.ppr: false. - التطبيق وراء Cloudflare بـ WAF بيمنع طلبات POST أكبر من 1MB أصلًا.
في الحالات دي، رقّي عادي مع الـ sprint الجاي. مش طارئ.
الخطوة التالية
افتح package.json دلوقتي وشوف إصدار next. لو في الرينج المكشوف، نفّذ الترقية في staging، اختبر بـ curl اللي فوق، وبعدين deploy على production. لو لقيت مشاكل غير متوقعة بعد الترقية، راجع الـ release notes بتاع 16.1.7 وابعتلي تفاصيل الـ stack trace.
المصادر
- NVD — CVE-2026-27979 Details: nvd.nist.gov/vuln/detail/CVE-2026-27979
- SentinelOne Vulnerability Database — CVE-2026-27979: sentinelone.com
- Next.js 16 Release Notes: nextjs.org/blog/next-16
- CWE-770 — Allocation of Resources Without Limits: cwe.mitre.org/data/definitions/770