Next.js 16: Migrasi middleware.ts ke proxy.ts

Foto oleh Taylor Vick on Unsplash
Di Next.js 16, dirilis 21 Oktober 2025, konvensi middleware.ts diganti namanya menjadi proxy.ts, dan fungsi yang diekspor berubah dari middleware menjadi proxy. Logikanya sama persis, tetapi proxy hanya berjalan pada runtime Node.js. Berkas middleware.ts yang tertinggal sudah usang dan diabaikan saat build.
Jalankan codemod upgrade resmi, npx @next/codemod@canary upgrade latest, yang memigrasikan konvensi untuk Anda. Untuk melakukannya manual, ganti nama middleware.ts menjadi proxy.ts, ganti fungsi yang diekspor menjadi proxy, dan ganti flag konfigurasi seperti skipMiddlewareUrlNormalize menjadi skipProxyUrlNormalize.
Tidak. proxy hanya berjalan pada runtime Node.js dan runtime-nya tidak dapat dikonfigurasi. Jika Anda benar-benar membutuhkan runtime Edge, untuk sekarang Anda tetap memakai berkas middleware.ts yang usang, hingga Next.js merilis panduan runtime Edge lebih lanjut pada rilis berikutnya.
Tidak. Dokumentasi Next.js menyatakan proxy tidak boleh dipakai sebagai solusi manajemen sesi atau otorisasi penuh, hanya untuk pemeriksaan optimistik. CVE-2025-29927 menunjukkan alasannya: header x-middleware-subrequest palsu dapat melewati middleware sepenuhnya. Otorisasi sesungguhnya berada di Server Components, Route Handlers, dan Server Actions Anda.
CVE-2025-29927 adalah celah Next.js dengan CVSS 9,1, diterbitkan 21 Maret 2025, yang memungkinkan penyerang melewati middleware dengan memalsukan header internal x-middleware-subrequest. Celah ini ditambal pada 12.3.5, 13.5.9, 14.2.25, dan 15.2.3. Pelajaran yang ditegaskan penggantian nama proxy adalah bahwa lapisan pencegat permintaan bukan batas keamanan.

Foto oleh Taylor Vick on Unsplash
Ringkasan Utama
Next.js 16, dirilis 21 Oktober 2025, mengganti nama berkas middleware.ts menjadi proxy.ts dan fungsi yang diekspor menjadi proxy. Logikanya sama persis, tetapi sekarang hanya berjalan pada runtime Node.js. Karena middleware.ts yang tertinggal diabaikan diam-diam, dan karena proxy bukan batas autentikasi, otorisasi harus berada di lapisan rute dan data Anda.
Jika Anda mengupgrade proyek ke Next.js 16 dan redirect login Anda diam-diam berhenti berjalan, penyebabnya hampir selalu sama: berkas middleware.ts Anda tidak lagi dijalankan. Next.js 16 mengganti nama seluruh konvensi ini. Saya mengalaminya di portofolio saya sendiri, dan perbaikannya bersifat mekanis — tetapi alasan di baliknya layak dipahami sebelum Anda mengganti nama satu berkas pun.
Tulisan ini menjelaskan persis apa yang berubah, codemod satu baris yang mengerjakan bagian membosankannya, jebakan yang membiarkan rute terproteksi terbuka lebar, dan satu pelajaran terpenting yang terus ditegaskan tim Next.js: lapisan pencegat permintaan tidak pernah dimaksudkan menjadi batas keamanan Anda.
Next.js 16 dirilis pada 21 Oktober 2025. Bersama Turbopack yang stabil dan Cache Components, ia mengganti nama middleware.ts menjadi proxy.ts. Berkas ini melakukan tugas yang sama — menjalankan kode sebelum sebuah permintaan selesai, sehingga Anda dapat menulis ulang, mengalihkan, atau memodifikasi header — tetapi namanya kini menggambarkan apa yang sebenarnya ia lakukan: sebuah proxy yang duduk di batas jaringan aplikasi Anda.
Dua hal ikut berubah bersama penggantian nama ini. Berkasnya menjadi proxy.ts, dan fungsi yang diekspor menjadi proxy. Flag konfigurasi yang membawa nama lama juga berubah — skipMiddlewareUrlNormalize menjadi skipProxyUrlNormalize. Satu detail sangat penting: proxy hanya berjalan pada runtime Node.js. Runtime edge tidak didukung di proxy, dan runtime-nya tidak dapat dikonfigurasi. Jika Anda benar-benar membutuhkan runtime edge, untuk sekarang Anda tetap menggunakan berkas middleware yang sudah usang.
// middleware.ts (Next.js 15 and earlier)
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
return NextResponse.redirect(new URL('/home', request.url))
}
export const config = {
matcher: '/about/:path*',
}
// ---------------------------------------------
// proxy.ts (Next.js 16+) — runs on the Node.js runtime
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
// same logic; only the file name and function name change
export function proxy(request: NextRequest) {
return NextResponse.redirect(new URL('/home', request.url))
}
export const config = {
matcher: '/about/:path*',
}Nama lama menyebabkan bertahun-tahun kebingungan dengan middleware bergaya Express, membuat fitur ini terdengar lebih serbaguna daripada kenyataannya. Membaca proxy.ts, rekan tim baru langsung tahu bahwa berkas ini mencegat permintaan di tepi jaringan alih-alih membungkus setiap handler di aplikasi Anda.
Penggantian nama ini sebagian bersifat kosmetik, tetapi terjadi dengan latar belakang keamanan yang nyata. CVE-2025-29927, diterbitkan 21 Maret 2025 dengan skor CVSS 9,1, memungkinkan penyerang melewati middleware Next.js sepenuhnya dengan mengirim header x-middleware-subrequest palsu. Header itu ada secara internal untuk mencegah middleware memanggil dirinya sendiri dalam loop; ketika dipercaya begitu saja, permintaan apa pun yang membawanya akan melompati eksekusi middleware.
Kalimat pada advisory tegas: dimungkinkan untuk melewati pemeriksaan otorisasi dalam aplikasi Next.js jika pemeriksaan otorisasi terjadi di middleware. Ini ditambal pada 12.3.5, 13.5.9, 14.2.25, dan 15.2.3 — tetapi pelajaran yang lebih dalam bertahan lebih lama dari tambalannya. Sebuah berkas yang mencegat permintaan di tepi adalah tempat yang salah untuk menjadi satu-satunya hal yang berdiri antara penyerang dan data Anda.
Perubahannya sendiri sepele. Codemod upgrade resmi versi 16 memigrasikan konvensi middleware ke proxy untuk Anda, beserta flag konfigurasi yang diganti namanya. Jika Anda lebih suka melakukannya secara manual, ganti nama berkas, ganti nama fungsi, dan perbarui setiap flag. Berikut keseluruhan prosedurnya.
# 1. Automated: the v16 upgrade codemod migrates the convention for you
npx @next/codemod@canary upgrade latest
# 2. Or do it by hand — rename the file
mv middleware.ts proxy.ts
# (then rename the exported function: middleware -> proxy)
# 3. Rename any config flags that carried the old name
# skipMiddlewareUrlNormalize -> skipProxyUrlNormalizeBerkas middleware.ts yang tertinggal diabaikan saat build di Next.js 16 tanpa error. Redirect dan penulisan ulang autentikasi Anda cukup berhenti berjalan, dan rute yang Anda kira terproteksi menjadi dapat diakses publik — diam-diam. Setelah upgrade, cari repositori Anda untuk berkas middleware yang tersasar dan pastikan ia diganti nama, bukan ditinggalkan.
Ini bagian yang harus dihayati. Dokumentasi Next.js menyatakan dengan jelas bahwa proxy tidak boleh digunakan sebagai solusi manajemen sesi atau otorisasi penuh. Ia baik untuk pemeriksaan optimistik — redirect cepat dengan upaya terbaik yang meningkatkan pengalaman — tetapi ia bukan kontrol keamanan. Pemeriksaan otorisasi yang sesungguhnya berada di tempat data berada.
Dalam praktiknya, itu berarti memverifikasi sesi di Server Components, Route Handlers, dan Server Actions Anda — sedekat mungkin dengan basis data. Lakukan pemeriksaan tepat sebelum Anda membaca atau mengubah data, bukan satu langkah lebih awal di batas permintaan. Jika proxy dilewati, dipalsukan, atau tidak sengaja diganti namanya, pemeriksaan di lapisan data tetap menahan garis. Proxy menjadi optimasi UX di atas penegakan yang nyata, bukan penegakan itu sendiri.
Masih ada tepi yang harus Anda perkuat. Khusus untuk CVE ini, mitigasi bagi siapa pun yang tidak dapat menambal segera adalah mencegah permintaan eksternal yang berisi header x-middleware-subrequest mencapai aplikasi Next.js Anda. Anda membuang atau memblokir header itu di load balancer, reverse proxy, atau CDN sebelum ia pernah mencapai aplikasi.
Platform terkelola seperti Vercel menerapkan proteksi ini secara otomatis, tetapi pada deployment self-hosted itu tanggung jawab Anda. Saya berjalan di belakang reverse proxy, jadi saya menjatuhkan header x-middleware-subrequest di sana sebagai pertahanan berlapis — bahkan pada versi yang sudah ditambal, tidak ada klien eksternal sah yang seharusnya mengirim header internal Next.js.
| Aspek | middleware.ts (15 dan sebelumnya) | proxy.ts (16 dan setelahnya) |
|---|---|---|
| Status berkas | Usang di Next.js 16, dihapus kemudian | Konvensi saat ini |
| Runtime | Edge atau Node.js | Hanya Node.js, tidak dapat dikonfigurasi |
| Fungsi yang diekspor | middleware | proxy |
| Flag konfigurasi | skipMiddlewareUrlNormalize | skipProxyUrlNormalize |
| Peran keamanan | Tidak pernah menjadi batas autentikasi nyata (CVE-2025-29927) | Tetap bukan batas autentikasi — hanya pemeriksaan optimistik |
Penggantian nama ini adalah diff kecil, tetapi perlakukan sebagai pengingat. Pindahkan setiap otorisasi nyata keluar dari proxy dan masukkan ke lapisan rute dan data Anda, buang header internal di tepi Anda, dan biarkan proxy melakukan satu hal yang dijanjikan nama barunya — mencegat permintaan di batas jaringan, tidak lebih.