رفتن به محتوا

Nuxt 4.6.4: هشت هشدار امنیتی و سه تغییر رفتاری در مسیرهای کش‌شده، صفحهٔ خطا و hostهای dev

۶ دقیقه مطالعه
nuxt
nitro
security

نسخه v4.6.4 از Nuxt در ۲ نوامبر منتشر شد، یک هفته بعد از 4.6.3. این هم یک نسخهٔ امنیتی است: یادداشت‌ها می‌گویند هشت هشدار در Nuxt را رفع می‌کند و با nitropack نسخهٔ 2.13.6 سه هشدار دیگر را در Nitro. یادداشت‌ها توصیه می‌کنند هرچه زودتر ارتقا دهید. هشدارها را جداگانه فهرست نمی‌کنند، پس نمی‌توانم شناسه، شدت یا بازهٔ نسخه‌های آسیب‌پذیر را بدهم. برای این موارد به صفحه‌های هشدار Nuxt و Nitro ارجاع می‌دهند.

چیزی که یادداشت‌ها صریحاً می‌گویند فهرست کوتاهی از تغییرهای رفتاری است که «احتمالاً بیشتر اپ‌ها را تحت تأثیر قرار نمی‌دهد». پیش از بالا بردن نسخه همین‌ها ارزش خواندن دارند، چون آنچه اپ برمی‌گرداند را عوض می‌کنند.

۱. صفحهٔ خطای production فقط جزئیات createError را نشان می‌دهد

وقتی رندر یک صفحه روی سرور شکست بخورد، صفحهٔ خطا و payload حالا فقط message و data خطاهایی را دارند که با createError ساخته شده‌اند. بقیهٔ جزئیات حذف می‌شود. یک رفع مرتبط در همین نسخه عنوانش «جزئیات خطاهای ناقابل‌اعتماد پرتاب‌شده را فاش نکن» است.

اگر عمداً خطا پرتاب می‌کنید مشکلی ندارید و حالا یک قرارداد روشن دارید:

ts
// pages/orders/[id].vue
const { data, error } = await useFetch(`/api/orders/${route.params.id}`);

if (!data.value) {
    throw createError({
        statusCode: 404,
        statusMessage: "Order not found",
        // `message` and `data` are what a production error page can carry
        message: "This order does not exist.",
        data: { orderId: route.params.id },
    });
}

پیامد برای کدی است که در production ویژگی‌های دیگری از خطای سمت سرور می‌خواند، مثلاً یک error.vue سفارشی که stack، cause یا یک فیلد سفارشی را نمایش می‌دهد. بعد از ارتقا این‌ها نخواهند بود. هرچه کاربر باید ببیند را در message یا data بگذارید و بقیه را در لاگ نگه دارید. یادداشت‌ها نمی‌گویند دقیقاً کدام ویژگی‌ها حذف می‌شوند، پس error.vue را با build production بررسی کنید، نه با nuxt dev.

۲. cache route ruleها پاسخ‌های کمتری ذخیره می‌کنند

سه تغییر در لایهٔ Nitro برای ruleهای cache، swr و isr آمده است:

  • فقط درخواست‌های GET و HEAD کش می‌شوند.
  • پاسخ‌هایی که cookie ست می‌کنند یا Cache-Control: private یا no-store می‌فرستند دیگر ذخیره نمی‌شوند.
  • ruleهای wildcard از نوع proxy و redirect درخواستی را رد می‌کنند که مقصد resolve‌شده‌اش از محدودهٔ rule بیرون بزند.
ts
// nuxt.config.ts
export default defineNuxtConfig({
    routeRules: {
        "/products/**": { swr: 60 },
        "/account/**": { cache: { maxAge: 30 } },
        "/legacy/**": { redirect: "/new/**" },
    },
});

قاعدهٔ cookie و private/no-store بیشترین اثر عملیاتی را دارد. صفحه‌ای زیر یک rule کش‌شده را در نظر بگیرید که در بعضی درخواست‌ها برای نشست یا رضایت‌نامه setCookie می‌زند. قبلاً چنین پاسخی می‌توانست ذخیره و برای دیگران تکرار شود؛ حالا ذخیره نمی‌شود. این رفتار امن‌تر است و با رفع افشای payload بین کاربران در صفحه‌های کش‌شده هم‌خوان است که نسخهٔ 4.5.1 در فهرست رفع‌هایش آورده است. هزینه‌اش پایین آمدن نرخ hit است اگر صفحه‌هایتان به‌طور اتفاقی cookie ست می‌کنند. بعد از ارتقا نرخ hit را زیر نظر بگیرید و اگر افت کرد، پاسخ‌هایی را پیدا کنید که cookie ست می‌کنند. همان‌ها هرگز برای اشتراک‌گذاری امن نبودند.

اگر بعد از 4.5.1 به همین دلیل کش CDN یا edge را پاک کردید، همین منطق اینجا هم صادق است: کشی که جلوی اپ است ممکن است هنوز پاسخ‌های ذخیره‌شده قبل از ارتقا را نگه دارد.

۳. route ruleها حالا slashهای encode‌شده را می‌بینند

ruleها حالا مسیرهای دارای slash کدگذاری‌شده را هم match می‌کنند. مثال یادداشت‌ها: /api%2Fadmin توسط rule‌ای با الگوی /api/** پوشش داده می‌شود. این از همان خانوادهٔ کار dot segment و حساسیت به حروف در 4.6.2 و 4.6.3 است: matcher و چیزی که در نهایت مسیر را resolve می‌کند باید هم‌نظر باشند. ruleی برای هدر یا no-store که یک URL با encode متفاوت می‌توانست از آن عبور کند، حالا اعمال می‌شود.

ایدهٔ smoke test نسخهٔ قبل را با یک حالت encode‌شده گسترش دهید:

bash
for p in /api/admin /API/admin /api%2Fadmin; do
  printf '%s -> ' "$p"
  curl -s -o /dev/null -D - --path-as-is "http://localhost:3000$p" | grep -i '^cache-control' || echo "(none)"
done

این اسکریپت از خودم است، نه از یادداشت‌های انتشار. آن را روی build production اجرا کنید، چون تغییرهای rule matching در لایهٔ Nitro هستند.

۴. dev serverها Host غیرمنتظره را رد می‌کنند

dev serverهای Webpack و rspack حالا درخواست‌هایی با هدر Host غیرمنتظره را رد می‌کنند. یادداشت‌ها می‌گویند این با رفتار فعلی Vite یکی است، پس کاربران Vite باید به آن عادت کرده باشند. این نسخه گزینهٔ devServer.allowedHosts را اضافه می‌کند. اگر با نام میزبان سفارشی یا تونل به dev server می‌رسید، آن host را به این گزینه اضافه کنید. صفحهٔ انتشار قالب مقدار پذیرفته‌شده را مستند نکرده، پس نحو دقیق را از مستندات پیکربندی Nuxt بخوانید و حدس نزنید.

یک تغییر کوچک‌تر مرتبط: وقتی workspaceDir تنظیم نشده باشد، Nuxt آن را فقط تا یک ریشهٔ workspace صریح یا نزدیک‌ترین مخزن git فراتر از rootDir می‌برد. در یک monorepo که بالاتر یک .git یا فایل workspace سرگردان دارد، دایرکتوری تشخیص‌داده‌شده، و با آن آنچه dev server اجازهٔ سرو دارد، ممکن است با قبل فرق کند.

موارد کوچک‌تر که باید بدانید

  • x-forwarded-proto فقط وقتی مورد اعتماد است که opt-in کنید (#36818). اگر TLS را جلوی Nuxt terminate می‌کنید و به پذیرفته‌شدن پیش‌فرض این هدر تکیه داشتید، بررسی کنید URLهای مطلق و redirectها هنوز https دارند. یادداشت‌ها نام تنظیم opt-in را نمی‌دهند، پس در مستندات پیدایش کنید.
  • tailهای wildcard در ruleهای غیرحساس به حروف حفظ می‌شوند و tail ریدایرکت‌های wildcard از segmentهای match‌شده resolve می‌شود.
  • hash مربوط به island از یک encoding بدون ابهام استفاده می‌کند و مستندات حالا دربارهٔ spread کردن اشیای ناقابل‌اعتماد روی server componentها هشدار می‌دهند.
  • nitropack باید 2.13.6 و unrouting باید 0.3.2 باشد؛ هر دو را همین نسخه بالا می‌برد.
  • خواندن body از طریق handler در nuxt/server حالا stream می‌شود (#36817).

چک‌لیست ارتقا

  1. npx nuxt upgrade را اجرا کنید و مطمئن شوید lockfile مقدار nitropack را 2.13.6 resolve می‌کند.
  2. production را محلی build و اجرا کنید، یک خطای سرور مدیریت‌شده و یکی مدیریت‌نشده راه بیندازید و ببینید error.vue همان چیزی را نشان می‌دهد که انتظار دارید.
  3. نرخ hit کش و رفتار Set-Cookie را روی صفحه‌های زیر ruleهای cache، swr یا isr مقایسه کنید.
  4. مسیرهای حساس route rule را با حروف ترکیبی، slashهای encode‌شده و dot segment امتحان کنید.
  5. اگر درخواست‌های dev شروع به شکست کردند، تونل یا hostهای سفارشی را به devServer.allowedHosts اضافه کنید.
  6. اگر پشت پراکسی terminate‌کنندهٔ TLS هستید، مدیریت scheme برای x-forwarded-proto را بررسی کنید.
  7. کش CDN جلوی مسیرهای کش‌شده را پاک کنید.

مصالحه‌ها و هشدارها

  • صفحهٔ انتشار شناسهٔ هشدار، شدت یا بازهٔ نسخه ندارد. پیش از تصمیم دربارهٔ فوریت برای استقرار خودتان دو صفحهٔ هشدار را بخوانید؛ خود یادداشت‌ها می‌گویند سریع ارتقا دهید.
  • چند رفع فقط یک خط توضیح دارند. توضیح‌های من دربارهٔ آن‌ها برداشت از عنوان‌هاست، نه از خود patchها.
  • سخت‌گیرانه‌تر کردن رفتار کش و خطا پیش‌فرض درستی است، اما تغییر رفتاری در یک patch release است. اجرای سبز CI نشان نمی‌دهد صفحهٔ خطایتان یک فیلد را از دست داده یا نرخ hit افت کرده؛ فقط تست‌ها و متریک‌های حالت production این را نشان می‌دهند.
  • آهنگ انتشار بالاست: 4.6.2، 4.6.3 و 4.6.4 در کمتر از سه هفته آمدند. نسخه را pin کنید و عمداً ارتقا دهید.

منابع