CVE-2026-22031
Description
@fastify/middie is the plugin that adds middleware support on steroids to Fastify. A security vulnerability exists in @fastify/middie prior to version 9.1.0 where middleware registered with a specific path prefix can be bypassed using URL-encoded characters (e.g., /%61dmin instead of /admin). While the middleware engine fails to match the encoded path and skips execution, the underlying Fastify router correctly decodes the path and matches the route handler, allowing attackers to access protected endpoints without the middleware constraints. Version 9.1.0 fixes the issue.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
@fastify/middienpm | < 9.1.0 | 9.1.0 |
Affected products
1Patches
1d44cd56eb724fix: decode paths before matching (#245)
3 files changed · +51 −1
lib/engine.js+3 −1 modified@@ -2,6 +2,7 @@ const reusify = require('reusify') const { pathToRegexp } = require('path-to-regexp') +const FindMyWay = require('find-my-way') function middie (complete) { const middlewares = [] @@ -98,7 +99,8 @@ function middie (complete) { const fn = middleware.fn const regexp = middleware.regexp if (regexp) { - const result = regexp.exec(url) + const decodedUrl = FindMyWay.sanitizeUrlPath(url) + const result = regexp.exec(decodedUrl) if (result) { req.url = req.url.replace(result[0], '') if (req.url[0] !== '/') {
package.json+1 −0 modified@@ -72,6 +72,7 @@ "dependencies": { "@fastify/error": "^4.0.0", "fastify-plugin": "^5.0.0", + "find-my-way": "^9.4.0", "path-to-regexp": "^8.1.0", "reusify": "^1.0.4" },
test/middleware.test.js+47 −0 modified@@ -217,6 +217,53 @@ test('middlewares with prefix', async t => { }) }) +test('middlewares for encoded paths', async t => { + t.plan(2) + + const instance = fastify() + instance.register(middiePlugin) + .after(() => { + instance.use('/encoded', function (req, _res, next) { + req.slashed = true + next() + }) + instance.use('/%65ncoded', function (req, _res, next) { + req.slashedSpecial = true + next() + }) + }) + + function handler (request, reply) { + reply.send({ + slashed: request.raw.slashed, + slashedSpecial: request.raw.slashedSpecial + }) + } + + instance.get('/encoded', handler) + instance.get('/%65ncoded', handler) + + const fastifyServerAddress = await instance.listen({ port: 0 }) + t.after(() => instance.server.close()) + + await t.test('decode the request url and run the middleware', async (t) => { + t.plan(2) + const response = await fetch(fastifyServerAddress + '/%65ncod%65d') // '/encoded' + t.assert.ok(response.ok) + const body = await response.json() + t.assert.deepStrictEqual(body, { slashed: true }) + }) + + await t.test('does not double decode the url', async (t) => { + t.plan(2) + const response = await fetch(fastifyServerAddress + '/%2565ncoded') + const body = await response.json() + + t.assert.ok(response.ok) + t.assert.deepStrictEqual(body, { slashedSpecial: true }) + }) +}) + test('res.end should block middleware execution', (t, done) => { t.plan(4)
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/fastify/middie/commit/d44cd56eb724490babf7b452fdbbdd37ea2effbanvdPatchWEB
- github.com/fastify/middie/pull/245nvdIssue TrackingPatchWEB
- github.com/fastify/middie/security/advisories/GHSA-cxrg-g7r8-w69pnvdExploitVendor AdvisoryWEB
- github.com/advisories/GHSA-cxrg-g7r8-w69pghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-22031ghsaADVISORY
- github.com/fastify/middie/releases/tag/v9.1.0nvdProductRelease NotesWEB
News mentions
0No linked articles in our index yet.