Published: June 2024
Severity: High
Affected: Next.js (Before 14.2.15)
Status: Patched in 14.2.15 and later
Overview
CVE-2024-51479 is a recent vulnerability discovered in Next.js, the widely-used full-stack React framework. When performing authorization in middleware that relies on pathnames, it was possible for root-level pages (like /foo) to bypass security checks. This bug can let an unauthorized user access certain protected pages, potentially exposing sensitive data.
If you are using Next.js before 14.2.15 and your app has custom authorization checks in middleware, your application might be at risk—unless you host on Vercel, which automatically patches this bug.
When creating web apps, it’s common to secure areas by checking the pathname in middleware
- / (homepage): *Not affected*
- /foo (root-level page): Affected
- /foo/bar (deeper paths): *Not affected*
Middleware logic that checks for /foo/* could fail to catch /foo itself due to the way paths are normalized internally in affected Next.js versions.
Example exploit:
If /foo is supposed to be restricted, but authorization is only enforced for /foo/*, anyone can just go to /foo and bypass security.
Here’s a vulnerable piece of middleware in Next.js
// middleware.js
import { NextResponse } from 'next/server';
export function middleware(request) {
const { pathname } = request.nextUrl;
// Intended to block access to /foo/* pages for unauthenticated users
if (pathname.startsWith('/foo/')) {
const isAuthenticated = checkSomeAuthCookie(request);
if (!isAuthenticated) {
return NextResponse.redirect('/login');
}
}
return NextResponse.next();
}
What's wrong?
- This checks for paths *starting with* /foo/ (like /foo/bar), but misses /foo itself.
- A malicious user can directly access https://example.com/foo and sneak past your middleware.
Real World Exploit Example
Imagine a page /foo showing private user data. You expect your middleware to block it unless the user is logged in. But with this bug, an attacker just types https://yoursite.com/foo into their browser and... access granted, no login needed.
Here’s a curl example of what an attacker could do
curl -i https://example.com/foo
# Server returns the content of /foo even if user isn't authorized
As long as the page is right under the root (not under /foo/bar), it’s vulnerable.
How Do I Fix It?
Update Next.js to 14.2.15 or later.
Run:
npm install next@latest
# or specify version
npm install next@14.2.15
Already using Vercel?
You're safe. Vercel applies a mitigation for this vulnerability—even if you haven’t upgraded Next.js yet.
Official Workarounds?
There are no official workarounds. The only solution is to upgrade.
To avoid this pitfall in *any* version, always check for both /foo and /foo/
export function middleware(request) {
const { pathname } = request.nextUrl;
// Secure: Check both /foo and any subroutes
if (pathname === '/foo' || pathname.startsWith('/foo/')) {
const isAuthenticated = checkSomeAuthCookie(request);
if (!isAuthenticated) {
return NextResponse.redirect('/login');
}
}
return NextResponse.next();
}
References & Resources
- Official Advisory: https://github.com/vercel/next.js/security/advisories/GHSA-gq73-gjwc-f83w
- Fix PR: https://github.com/vercel/next.js/pull/64123
- Next.js Release notes: https://github.com/vercel/next.js/releases/tag/v14.2.15
- CVE Record: https://nvd.nist.gov/vuln/detail/CVE-2024-51479
Summary
If you have custom authorization checks in Next.js middleware based on pathnames, your app might unintentionally allow unauthorized access to root-level pages.
Upgrade Next.js to 14.2.15 or later right away to stay safe. And remember—when matching paths, always consider exact matches for root-level routes as well as subroutes.
Timeline
Published on: 12/17/2024 19:15:06 UTC