CVE-2026-33808
@fastify/express vulnerable to middleware authentication bypass via URL normalization gaps (duplicate slashes and semicolons)
Impact@fastify/express v4.0.4 and earlier fails to normalize URLs before passing them to Express middleware when Fastify router normalization options are enabled. This allows complete bypass of path-scoped authentication middleware via duplicate slashes when ignoreDuplicateSlashes is enabled, or via semicolon delimiters when useSemicolonDelimiter is enabled. In both cases, Fastify router normalizes the URL and matches the route, but @fastify/express passes the original un-normalized URL to Express middleware, which fails to match and is skipped. An unauthenticated attacker can access protected routes by manipulating the URL path.
PatchesUpgrade to @fastify/express v4.0.5 or later.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
9.1
@fastify/express vulnerable to middleware authentication bypass via URL normalization gaps (duplicate slashes and semicolons)
Impact@fastify/express v4.0.4 and earlier fails to normalize URLs before passing them to Express middleware when Fastify router normalization options are enabled. This allows complete bypass of path-scoped authentication middleware via duplicate slashes when ignoreDuplicateSlashes is enabled, or via semicolon delimiters when useSemicolonDelimiter is enabled. In both cases, Fastify router normalizes the URL and matches the route, but @fastify/express passes the original un-normalized URL to Express middleware, which fails to match and is skipped. An unauthenticated attacker can access protected routes by manipulating the URL path.
PatchesUpgrade to @fastify/express v4.0.5 or later.
- Record
CVE-2026-33808- CVSS 4.0
- 9.1 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-436
- Updated
- 2026-11-02
EUVDEUVD-2026-22881
9.1
Impact@fastify/express v4.0.4 and earlier fails to normalize URLs before passing them to Express middleware when Fastify router normalization options are enabled. This allows complete bypass of path-scoped authentication middleware via duplicate slashes when ignoreDuplicateSlashes is enabled, or via semicolon delimiters when useSemicolonDelimiter is enabled. In both cases, Fastify router normalizes the URL and matches the route, but @fastify/express passes the original un-normalized URL to Express middleware, which fails to match and is skipped. An unauthenticated attacker can access protected routes by manipulating the URL path.
PatchesUpgrade to @fastify/express v4.0.5 or later.
- Record
EUVD-2026-22881- CVSS 4.0
- 9.1 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-6hw5-45gm-fj88
9.1
@fastify/express has a middleware authentication bypass via URL normalization gaps (duplicate slashes and semicolons)
Summary
@fastify/express v4.0.4 fails to normalize URLs before passing them to Express middleware when Fastify router normalization options are enabled. This allows complete bypass of path-scoped authentication middleware via two vectors:
- Duplicate slashes (
//admin/dashboard) whenignoreDuplicateSlashes: trueis configured - Semicolon delimiters (
/admin;bypass) whenuseSemicolonDelimiter: trueis configured
In both cases, Fastify's router normalizes the URL and matches the route, but @fastify/express passes the original un-normalized URL to Express middleware, which fails to match and is skipped.
Note: This is distinct from GHSA-g6q3-96cp-5r5m (CVE-2026-22037), which addressed URL percent-encoding bypass and was patched in v4.0.3. These normalization gaps remain in v4.0.4. A similar class of normalization issue was addressed in @fastify/middie via GHSA-8p85-9qpw-fwgw (CVE-2026-2880), but @fastify/express does not include the equivalent fixes.
Details
The vulnerability exists in @fastify/express's enhanceRequest function (index.js lines 43-46):
const decodedUrl = decodeURI(url)
req.raw.url = decodedUrl
The decodeURI() function only handles percent-encoding — it does not normalize duplicate slashes or strip semicolon-delimited parameters. When Fastify's router options are enabled, find-my-way applies these normalizations during route matching, but @fastify/express passes the original URL to Express middleware.
Vector 1: Duplicate Slashes
When ignoreDuplicateSlashes: true is set, Fastify's find-my-way router normalizes //admin/dashboard to /admin/dashboard for route matching. However, Express middleware receives //admin/dashboard. Express's app.use('/admin', authMiddleware) expects paths to start with /admin/, but //admin does not match the /admin prefix pattern.
The attack sequence:
- Client sends
GET //admin/dashboard - Fastify's router normalizes this to
/admin/dashboardand finds a matching route enhanceRequestsetsreq.raw.url = "//admin/dashboard"(preserves double slash)- Express middleware
app.use('/admin', authMiddleware)does not match//adminprefix - Authentication is bypassed, and the Fastify route handler executes
Vector 2: Semicolon Delimiters
When useSemicolonDelimiter: true is configured, the router uses find-my-way's safeDecodeURI() which treats semicolons as query string delimiters, splitting /admin;bypass into path /admin and querystring bypass for route matching. However, @fastify/express passes the full URL /admin;bypass to Express middleware.
Express uses path-to-regexp v0.1.12 internally, which compiles middleware paths like /admin to the regex /^\/admin\/?(?=\/|$)/i. A semicolon character does not satisfy the lookahead condition, causing the middleware match to fail.
The attack flow:
- Request
GET /admin;bypassarrives - Fastify router: splits at
;— matches routeGET /admin - Express middleware: regex
/^\/admin\/?(?=\/|$)/ifails against/admin;bypass— middleware skipped - Route handler executes without authentication checks
PoC
Duplicate Slash Bypass
Save as server.js and run with node server.js:
const fastify = require('fastify')
async function start() {
const app = fastify({
logger: false,
ignoreDuplicateSlashes: true, // documented Fastify option
})
await app.register(require('@fastify/express'))
// Standard Express middleware auth pattern
app.use('/admin', function expressAuthGate(req, res, next) {
const auth = req.headers.authorization
if (!auth || auth !== 'Bearer admin-secret-token') {
res.statusCode = 403
res.setHeader('content-type', 'application/json')
res.end(JSON.stringify({ error: 'Forbidden by Express middleware' }))
return
}
next()
})
// Protected route
app.get('/admin/dashboard', async (request) => {
return { message: 'Admin…
- Record
GHSA-6hw5-45gm-fj88- CVSS 4.0
- 9.1 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N - CVSS 3.1
- 9.1 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N - Weakness
- CWE-436
- Updated
- 2026-11-02
NVD
9.1
Impact@fastify/express v4.0.4 and earlier fails to normalize URLs before passing them to Express middleware when Fastify router normalization options are enabled. This allows complete bypass of path-scoped authentication middleware via duplicate slashes when ignoreDuplicateSlashes is enabled, or via semicolon delimiters when useSemicolonDelimiter is enabled. In both cases, Fastify router normalizes the URL and matches the route, but @fastify/express passes the original un-normalized URL to Express middleware, which fails to match and is skipped. An unauthenticated attacker can access protected routes by manipulating the URL path.
PatchesUpgrade to @fastify/express v4.0.5 or later.
- Record
CVE-2026-33808- CVSS 4.0
- 9.1 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 9.1 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N - Weakness
- CWE-436
- Updated
- 2026-11-02
OSV
9.1
@fastify/express vulnerable to middleware authentication bypass via URL normalization gaps (duplicate slashes and semicolons)
Impact@fastify/express v4.0.4 and earlier fails to normalize URLs before passing them to Express middleware when Fastify router normalization options are enabled. This allows complete bypass of path-scoped authentication middleware via duplicate slashes when ignoreDuplicateSlashes is enabled, or via semicolon delimiters when useSemicolonDelimiter is enabled. In both cases, Fastify router normalizes the URL and matches the route, but @fastify/express passes the original un-normalized URL to Express middleware, which fails to match and is skipped. An unauthenticated attacker can access protected routes by manipulating the URL path.
PatchesUpgrade to @fastify/express v4.0.5 or later.
- Record
CVE-2026-33808- CVSS 4.0
- 9.1 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-436
- Updated
- 2026-11-02
OSVGHSA-6hw5-45gm-fj88
9.1
@fastify/express has a middleware authentication bypass via URL normalization gaps (duplicate slashes and semicolons)
Summary
@fastify/express v4.0.4 fails to normalize URLs before passing them to Express middleware when Fastify router normalization options are enabled. This allows complete bypass of path-scoped authentication middleware via two vectors:
- Duplicate slashes (
//admin/dashboard) whenignoreDuplicateSlashes: trueis configured - Semicolon delimiters (
/admin;bypass) whenuseSemicolonDelimiter: trueis configured
In both cases, Fastify's router normalizes the URL and matches the route, but @fastify/express passes the original un-normalized URL to Express middleware, which fails to match and is skipped.
Note: This is distinct from GHSA-g6q3-96cp-5r5m (CVE-2026-22037), which addressed URL percent-encoding bypass and was patched in v4.0.3. These normalization gaps remain in v4.0.4. A similar class of normalization issue was addressed in @fastify/middie via GHSA-8p85-9qpw-fwgw (CVE-2026-2880), but @fastify/express does not include the equivalent fixes.
Details
The vulnerability exists in @fastify/express's enhanceRequest function (index.js lines 43-46):
const decodedUrl = decodeURI(url)
req.raw.url = decodedUrl
The decodeURI() function only handles percent-encoding — it does not normalize duplicate slashes or strip semicolon-delimited parameters. When Fastify's router options are enabled, find-my-way applies these normalizations during route matching, but @fastify/express passes the original URL to Express middleware.
Vector 1: Duplicate Slashes
When ignoreDuplicateSlashes: true is set, Fastify's find-my-way router normalizes //admin/dashboard to /admin/dashboard for route matching. However, Express middleware receives //admin/dashboard. Express's app.use('/admin', authMiddleware) expects paths to start with /admin/, but //admin does not match the /admin prefix pattern.
The attack sequence:
- Client sends
GET //admin/dashboard - Fastify's router normalizes this to
/admin/dashboardand finds a matching route enhanceRequestsetsreq.raw.url = "//admin/dashboard"(preserves double slash)- Express middleware
app.use('/admin', authMiddleware)does not match//adminprefix - Authentication is bypassed, and the Fastify route handler executes
Vector 2: Semicolon Delimiters
When useSemicolonDelimiter: true is configured, the router uses find-my-way's safeDecodeURI() which treats semicolons as query string delimiters, splitting /admin;bypass into path /admin and querystring bypass for route matching. However, @fastify/express passes the full URL /admin;bypass to Express middleware.
Express uses path-to-regexp v0.1.12 internally, which compiles middleware paths like /admin to the regex /^\/admin\/?(?=\/|$)/i. A semicolon character does not satisfy the lookahead condition, causing the middleware match to fail.
The attack flow:
- Request
GET /admin;bypassarrives - Fastify router: splits at
;— matches routeGET /admin - Express middleware: regex
/^\/admin\/?(?=\/|$)/ifails against/admin;bypass— middleware skipped - Route handler executes without authentication checks
PoC
Duplicate Slash Bypass
Save as server.js and run with node server.js:
const fastify = require('fastify')
async function start() {
const app = fastify({
logger: false,
ignoreDuplicateSlashes: true, // documented Fastify option
})
await app.register(require('@fastify/express'))
// Standard Express middleware auth pattern
app.use('/admin', function expressAuthGate(req, res, next) {
const auth = req.headers.authorization
if (!auth || auth !== 'Bearer admin-secret-token') {
res.statusCode = 403
res.setHeader('content-type', 'application/json')
res.end(JSON.stringify({ error: 'Forbidden by Express middleware' }))
return
}
next()
})
// Protected route
app.get('/admin/dashboard', async (request) => {
return { message: 'Admin…
- Record
GHSA-6hw5-45gm-fj88- CVSS 4.0
- 9.1 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N - CVSS 3.1
- 9.1 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N - Weakness
- CWE-436
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
@fastify/expressnpm |
through 4.0.4 | 4.0.5 |
@fastify/expressnpm |
before 4.0.5 | 4.0.5 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-33808 is a critical vulnerability (CVSS 9.1) in Fastify @fastify/express, published April 15, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.48%, the 41st percentile. Fixed in @fastify/express 4.0.5.
References
github.com/fastify/fastify-express/security/advisories/GHSA-6hw5-45gm-fj88
cna.openjsf.org/security-advisories.html
nvd.nist.gov/vuln/detail/CVE-2026-33808
github.com/advisories/GHSA-6hw5-45gm-fj88
github.com/CVEProject/cvelistV5/tree/main/cves/2026/33xxx/CVE-2026-33808.json
github.com/fastify/fastify-express
Left out here: the rest of 2 source descriptions. The JSON record has them.