رفتن به محتوا
بلاگNext.js

دو انتشار امنیتی Next.js در نه روز: چه چیزی را باید به‌روز کنید

۵ دقیقه مطالعه
Next.js
Security

سپتامبر ۲۰۲۶ برای امنیت Next.js ماه پرکاری بود. یک انتشار خارج از برنامه در ۲۲ سپتامبر یک مشکل بحرانی اجرای کد از راه دور (RCE) را در next/og رفع کرد و انتشار برنامه‌ریزی‌شده ۳۰ سپتامبر مجموعه‌ای از رفع‌ایرادها را در حوزه کش، بهینه‌ساز تصویر و مسیرهای متادیتا آورد. اگر Next.js را در محیط production اجرا می‌کنید، احتمالاً باید برای هر دو اقدام کنید.

انتشار اول: ۲۲ سپتامبر، RCE بحرانی در ImageResponse

طبق به‌روزرسانی امنیتی رسمی، نسخه‌های 16.3.6 (Active LTS) و 15.5.26 (Maintenance LTS) وابستگی‌های بالادستی از جمله Satori را به‌روز کرده‌اند تا مشکلی که می‌توانست به اجرای کد از راه دور برسد بسته شود.

نکاتی که برای ارزیابی اهمیت دارند:

  • شناسه توصیه‌نامه GHSA-vcvr-r3jv-pc5j است و یک توصیه‌نامه مرتبط هم در Satori وجود دارد.
  • بازه تحت تأثیر: >=16.2.0 <16.3.6.
  • مشکل در پیاده‌سازی Node.js از ImageResponse در next/og است. escape نادرست در خروجی SVG که Satori تولید می‌کند، در شرایط خاص و از طریق آسیب‌پذیری‌های وابستگی‌های دیگر، می‌توانست به RCE منجر شود.
  • پیاده‌سازی Edge از ImageResponse تحت تأثیر نیست.
  • نسخه 15.5.26 سخت‌سازی مرتبط دارد، اما Next.js 15.x از خود RCE تأثیر نمی‌پذیرد.

پیامد عملی این است که دامنه آسیب به انتخاب runtime بستگی دارد. مسیری مانند زیر در نسخه‌های 16.2.0 تا 16.3.5 در محدوده آسیب‌پذیر است:

ts
// app/og/route.tsx — Node.js runtime (the default), affected before 16.3.6
import { ImageResponse } from "next/og";

export async function GET(request: Request) {
    const title = new URL(request.url).searchParams.get("title") ?? "Hello";
    return new ImageResponse(<div style={{ fontSize: 64 }}>{title}</div>, {
        width: 1200,
        height: 630,
    });
}

این را الگویی برای بازبینی بدانید: ورودی کنترل‌شده توسط کاربر که در runtime ِ Node.js به تولیدکننده تصویر OG می‌رسد. انتقال این مسیرها به Edge جایگزین ارتقا نیست، اما چون توصیه‌نامه می‌گوید پیاده‌سازی Edge آسیب‌پذیر نیست، می‌تواند تا پایان rollout میزان مواجهه را کم کند. عملی بودن این کار به میزبانی شما و به آنچه مسیر import می‌کند بستگی دارد.

انتشار دوم: ۳۰ سپتامبر، رفع‌ایرادهای برنامه‌ریزی‌شده

تیم Next.js در پیش‌اعلان که ۲۳ سپتامبر منتشر شد، قبلاً خبر داده بود. یادداشتی که ۲۹ سپتامبر اضافه شد می‌گوید 16.3.7 فقط یک رفع باگ داشت و رفع‌ایرادهای امنیتی در عوض در 16.3.8 و 15.5.27 می‌آیند.

پیش‌اعلان از نه آسیب‌پذیری خبر می‌داد: یک بحرانی، دو بالا، پنج متوسط و یک پایین. من نتوانستم متن کامل توصیه‌نامه رسمی انتشار ۳۰ سپتامبر را بخوانم؛ نشانی آن هنگام تلاش من پیدا نشد. تنها خلاصه پس از انتشار که توانستم بخوانم گزارش تغییرات Netlify است و هفت مورد را شرح می‌دهد: یک بالا، پنج متوسط و یک پایین. این دو شمارش با هم نمی‌خوانند. شاید مورد بحرانی پیش‌اعلان همان مشکل ۲۲ سپتامبر باشد که قبلاً رفع شده، اما این استنباط خود من است و هیچ‌کدام از منابع آن را نمی‌گویند. پیش از تصمیم درباره ریسک، فهرست معتبر را از توصیه‌نامه‌های رسمی در GitHub بررسی کنید.

بر اساس خلاصه Netlify، موارد شامل این‌هاست:

  • بالا: SSRF در بهینه‌ساز تصویر، که شامل پیکربندی‌های 16.x با میزبان‌های راه دور کنترل‌شده توسط مهاجم می‌شود.
  • متوسط: مسموم‌سازی کش برای صفحات SSG/ISR، افشای اطلاعات از طریق مسیرهای تصویر متادیتا، نشت کش در کامپوننت‌های تودرتو، و افشای محتوای Draft Mode.
  • پایین: افشای اطلاعات از سرور توسعه.

Netlify همچنین می‌گوید روی پلتفرم خودش سه مورد (SSRF تصویر، نشت Draft Mode و افشای سرور توسعه) به دلیل CDN تصویر و معماری serverless اعمال نمی‌شوند. بیلدهای Webpack، SSG/ISR با مسیرهای catch-all و پیکربندی‌های Cache Components همچنان آسیب‌پذیرند. این گزاره درباره یک میزبان است؛ فرض نکنید پلتفرم شما هم همین محافظت‌ها را دارد.

چه باید کرد

به نسخه‌ای ارتقا دهید که هر دو دور رفع‌ایراد را دارد:

bash
# 16.x line
pnpm add next@16.3.8

# 15.x line
pnpm add next@15.5.27

سپس:

  1. lockfile را بررسی کنید، نه فقط package.json را. با بازه‌های caret، lockfile قدیمی شما را روی نسخه آسیب‌پذیر نگه می‌دارد. در هر پکیج workspace دستور pnpm why next را اجرا کنید، چون در monorepoها اغلب چند نسخه پین شده است.
  2. آداپتور پلتفرم را به‌روز کنید. راهنمای Netlify شامل ارتقای @netlify/plugin-nextjs به 5.16.1 و redeploy است. میزبان‌های دیگر آداپتور یا runtime مخصوص خود را دارند؛ دنبال به‌روزرسانی آن‌ها باشید.
  3. همه چیز را redeploy کنید، از جمله previewها. Netlify پیشنهاد می‌کند حذف deployهای preview و branch آسیب‌پذیر را در نظر بگیرید، چون کد قدیمی را همچنان سرو می‌کنند.
  4. اگر پشت CDN به SSG/ISR تکیه دارید، پس از ارتقا کش مشترک را پاک کنید. وصله‌کردن کد پاسخ‌های مسموم‌شده را از کش بیرون نمی‌اندازد. این یک اصل عمومی مدیریت کش است و در توصیه‌نامه‌ها نیامده؛ آن را با ترافیک و پیکربندی خودتان بسنجید.
  5. مسیرهای تصویر OG را بازبینی کنید و هر ورودی کنترل‌شده توسط کاربر را در آن‌ها مخرب فرض کنید.

مصالحه‌ها و نکات احتیاطی

  • جاافتادن 16.3.7. این نسخه هیچ رفع امنیتی نداشت؛ پایپ‌لاینی که خودکار به «آخرین patch/minor» می‌رود و همان‌جا می‌ایستد، آسیب‌پذیر می‌ماند. صراحتاً روی نسخه‌های رفع‌شده پین کنید یا مرحله audit بگذارید.
  • 15.x در برابر 16.x. شاخه 15.5 برای مشکل اول سخت‌سازی گرفت ولی در برابر RCE آسیب‌پذیر نبود. هنوز در دامنه رفع‌ایرادهای ۳۰ سپتامبر است، چون 15.5.27 برای همین منتشر شده است.
  • ریسک ارتقا صفر نیست. انتشارهای patch در شاخه‌های LTS محافظه‌کارانه‌اند، اما باید تست‌های E2E را روی نسخه جدید اجرا کنید، به‌ویژه برای بهینه‌سازی تصویر و رفتار ISR که دقیقاً بخش‌های دست‌خورده‌اند.
  • اعلام پیشاپیش دو لبه دارد. یک هفته مهلت به تیم‌ها وقت می‌دهد deploy را برنامه‌ریزی کنند، اما به مهاجمان هم می‌گوید مجموعه‌ای از رفع‌ایرادها در راه است؛ ارتقا را به انتهای بازه موکول نکنید.

جمع‌بندی

دو انتشار، دو مشکل متفاوت: یک RCE ناشی از وابستگی‌ها در مسیر Node.js ِ ImageResponse، و یک دسته برنامه‌ریزی‌شده در حوزه کش، بهینه‌سازی تصویر و مسیرهای متادیتا. راه‌حل در هر دو یکی است: 16.3.8 یا 15.5.27 را نصب کنید، lockfile را بررسی کنید، همه محیط‌ها را redeploy کنید و فهرست دقیق مربوط به پیکربندی خود را از توصیه‌نامه‌های رسمی بخوانید.

منابع