Apr 16, 2026·6 min read·1 visit
@fastify/express <= 4.0.4 incorrectly doubles path prefixes during child plugin registration, bypassing security middleware on encapsulated child routes.
A critical vulnerability exists in @fastify/express versions 4.0.4 and earlier where an interpretation conflict causes middleware paths to be incorrectly calculated during plugin inheritance. This flaw allows unauthenticated remote attackers to bypass security middleware, such as authentication and authorization controls, on specific routes defined within child plugin scopes.
The @fastify/express package serves as a compatibility layer for integrating legacy Express middleware into the Fastify ecosystem. It allows developers to utilize established Express ecosystem tools for authentication, rate limiting, and request validation without rewriting them as Fastify-native hooks. This component maps Express's middleware execution model onto Fastify's encapsulated routing architecture.
The vulnerability is classified as an interpretation conflict (CWE-436) occurring within the plugin registration lifecycle. Specifically, the flaw exists in how the package clones parent scope state into newly initialized child plugins via the onRegister hook. Fastify relies on this mechanism to ensure that middleware registered at a higher level applies symmetrically to lower-level encapsulated routes.
Due to incorrect path calculation logic, the compatibility layer fails to bind the inherited middleware to the correct paths in the child scope. This results in an absolute bypass of the security controls enforced by that middleware for all matching child routes. An attacker can access restricted endpoints without supplying required credentials or passing required validation steps.
The root cause originates in the prefix calculation logic used by the @fastify/express compatibility layer prior to version 4.0.5. The custom use(path, fn) method prepends the current Fastify instance prefix to the provided path argument. This computed string is then stored internally alongside the middleware function in a collection identified by the kMiddlewares symbol.
Fastify utilizes an onRegister hook to clone parent state into newly registered child plugins. The vulnerable implementation of this hook iterates over the parent's stored kMiddlewares collection to propagate the configurations. For each entry, it invokes the child instance's use method, passing the previously computed and stored path.
The failure condition triggers when the child instance receives this path argument. Because the child's use method independently prepends its own prefix, and the provided path is already prefixed from the parent, the resulting route binding is doubled. For example, a middleware intended for /admin becomes bound to /admin/admin.
Furthermore, a secondary interpretation conflict exists regarding path normalization. Fastify's native router can be configured to ignore duplicate slashes. If the Express middleware engine processes paths without an identical normalization rule, an attacker can append redundant slashes to force a string mismatch, bypassing the middleware entirely while still reaching the destination Fastify route.
An analysis of the vulnerable code path reveals reliance on the decorated instance.use() method during the inheritance lifecycle. This method inherently applies the current scope's prefix to whatever path argument it receives. The logic assumes it is receiving an un-prefixed base path, which is false during onRegister cloning operations.
The primary logic correction in commit c4e49b5244fcfadb38dc08e9b1808c5d759021a2 changes how the middleware is applied to the child instance. The developers modified the onRegister hook to bypass the decorated use method entirely. By invoking the underlying Express instance directly via instance.express.use(path, fn), the redundant prefixing logic is avoided.
The secondary fix implemented in commit 674020f27ddc1d1709e4369cb40158d4c958d42b addresses the normalization discrepancy. This change introduces a normalizeUrl utility function within the middleware pipeline. It synchronizes the incoming request URL format with Fastify's internal routerOptions, ensuring that both routing layers evaluate paths identically regardless of duplicate slashes.
Exploitation requires specific architectural preconditions within the target application. The application must utilize @fastify/express version 4.0.4 or earlier. Additionally, it must implement child plugins that define endpoints overlapping with the prefix of a parent-level middleware block. The middleware in question must be responsible for access control or security validation.
To execute the attack, an unauthenticated remote actor sends an HTTP request targeting a valid endpoint within the vulnerable child plugin scope. Because the security middleware is improperly bound to the doubled path structure, the application evaluates the request without invoking the middleware chain. The underlying Fastify route handler processes the request normally.
The public Proof-of-Concept demonstrates this by establishing a root scope that enforces authentication on the /admin path. A child plugin is subsequently registered with the same /admin prefix, containing a restricted /secret route. The root-level route correctly returns a 403 Forbidden status when accessed without credentials.
When the attacker requests the /admin/secret endpoint, the server returns a 200 OK status alongside the restricted data. The authentication middleware is bypassed because it is internally listening on /admin/admin/*. The discrepancy allows unauthorized access with low complexity.
The vulnerability directly undermines the core access control mechanisms of the affected application. Bypassing authentication or authorization middleware grants unauthenticated users the same operational capabilities as authenticated administrators or users. This facilitates unauthorized access to sensitive data and allows the execution of restricted state-modifying functions.
The application scope is broadly impacted by this flaw. Any endpoint defined within an affected child plugin loses the protection of the parent's Express middleware. This structural failure breaks the expected security boundaries defined by developers, leading to systemic exposure of encapsulated routes.
The CVSS v3.1 vector evaluates to 9.1 (Critical). The base score is driven by the lack of required privileges and the absence of user interaction. The attack relies solely on standard network requests and has low complexity, making it trivial to automate against affected infrastructure.
The EPSS score is currently low at 0.00052, reflecting the recent disclosure date. However, the availability of a clear Proof-of-Concept significantly increases the likelihood of active exploitation. Security teams should prioritize remediation to prevent unauthorized data access.
The definitive remediation is to upgrade the @fastify/express dependency to version 4.0.5 or later. This release contains the necessary structural patches to ensure path variables are correctly inherited and normalized during plugin registration. Application owners should update their package.json and regenerate their lockfiles to pull the correct transitive dependencies.
In environments where immediate patching is unfeasible, developers must restructure their application architecture. Refactoring the codebase to use Fastify-native hooks (onRequest, preHandler) for security controls eliminates reliance on the vulnerable compatibility layer. Alternatively, developers can avoid using prefixed child plugins in conjunction with Express security middleware.
Validation of the fix requires testing the application routing logic. Security engineers should execute unauthenticated requests against all previously protected child plugin endpoints in a staging environment. Verification is successful when these requests return the expected 401 Unauthorized or 403 Forbidden responses.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
@fastify/express Fastify | <= 4.0.4 | 4.0.5 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-436 |
| Attack Vector | Network |
| CVSS Base Score | 9.1 (Critical) |
| EPSS Score | 0.00052 |
| Exploit Status | Proof-of-Concept Available |
| KEV Status | Not Listed |
Interpretation Conflict