Oct 1, 2026·5 min read·6 visits
Unauthenticated remote attackers can bypass route-level security hooks and access protected not-found handlers in sibling plugins by crafting malformed HTTP requests.
An authentication bypass vulnerability in the Fastify web framework allows remote attackers to access private custom not-found handlers by submitting requests with malformed URLs. This bypasses the typical request lifecycle and its associated authorization hooks.
Fastify is a high-performance web framework for the Node.js ecosystem that relies on a strict plugin encapsulation model. In this architecture, registering a plugin with a prefix isolates route definitions, custom not-found handlers, and request lifecycle hooks (such as preHandler or onRequest). Security and authentication policies are traditionally enforced through these prefix-level hooks.
A severe vulnerability exists in Fastify versions starting from 4.0.0 up to but excluding 5.12.2. Due to a design flaw in the internal 404 router, requests containing malformed URI structures can trigger an alternate routing pathway. This alternate path routes requests to the custom not-found handler of an unrelated sibling or private plugin prefix.
Because this fallback bypasses the primary request lifecycle execution chain, the target not-found handler is executed without invoking any authorization or authentication hooks. This behavior corresponds to CWE-288: Authentication Bypass Using an Alternate Path or Channel.
The root cause of this vulnerability lies in the implementation of the 404 routing logic within lib/four-oh-four.js. The module sets up a routing instance via find-my-way to handle cases where a matching route is not found. To handle exceptions such as invalid URLs, the 404 router configures handlers for onBadUrl and onMaxParamLength using an internal helper named createRouteEventHandler().
Inside lib/four-oh-four.js, a module-scoped lexical variable called _routeEventHandler is initialized to null. When any encapsulated plugin registers a custom 404 handler via setNotFoundHandler(), this shared variable is overwritten with the most recently registered handler. Consequently, registering multiple encapsulated plugins with distinct 404 handlers causes the last-registered handler to overwrite _routeEventHandler globally across all other prefixes.
When a client submits a request with a malformed URL (e.g., featuring invalid percent-encoding like %c0) using an unhandled HTTP method, the router fails to resolve a valid path. It falls back to the 404 routing logic, triggering the onBadUrl hook. The onRouteEvent callback executes and immediately invokes _routeEventHandler directly. This direct execution circumvents Fastify's normal request lifecycle hooks, resulting in an unauthenticated invocation of the target handler.
In vulnerable versions, the lib/four-oh-four.js file maintains a shared _routeEventHandler variable and binds custom event handlers directly to it. This design leaks handler contexts across different encapsulated scopes.
Below is the vulnerable implementation:
// VULNERABLE CODE (lib/four-oh-four.js)
function fourOhFour (options) {
const router = FindMyWay({
onBadUrl: createRouteEventHandler(),
onMaxParamLength: createRouteEventHandler(),
defaultRoute: fourOhFourFallBack
})
let _routeEventHandler = null // Shared lexical variable
function setNotFoundHandler (opts, handler) {
if (handler) {
this[kFourOhFourLevelInstance][kCanSetNotFoundHandler] = false
handler = handler.bind(this)
_routeEventHandler = handler // Overwrites the shared pointer globally
} else {
handler = basic404
_routeEventHandler = basic404
}
}
}The corresponding patch removes the shared _routeEventHandler variable. It delegates onBadUrl and onMaxParamLength directly to the routerOptions object defined at the root level. This stops the execution flow from cascading down to custom 404 handlers altogether when a malformed request is detected.
// PATCHED CODE (lib/four-oh-four.js)
function fourOhFour (options) {
const router = FindMyWay({
// Delegate directly to the options object without a shared handler pointer
onBadUrl: options.routerOptions.onBadUrl,
onMaxParamLength: options.routerOptions.onMaxParamLength,
defaultRoute: fourOhFourFallBack
})
// The shared variable _routeEventHandler is entirely removed.
}Exploitation requires the target Fastify application to have at least two sibling or hierarchical plugins. One plugin represents a public or unauthenticated scope, while another represents a private, protected scope requiring credentials verified via hooks. Both scopes must declare custom not-found handlers.
The attacker identifies an HTTP method that is not registered under the public path (for example, sending a DELETE request to a prefix that only serves GET endpoints). The attacker then submits this unhandled HTTP request utilizing a malformed URL structure.
Upon processing this request, Fastify's router transitions to the 404 handler fallback due to the unhandled HTTP method. The malformed nature of the URI subsequently triggers the onBadUrl event handler. Fastify then invokes the globally shared _routeEventHandler (which points to the private 404 handler), executing it directly and bypassing the authorization lifecycle.
The security impact of this vulnerability is high. It permits unauthenticated, remote attackers to access private and protected execution scopes. Any data returned by custom 404 handlers residing in private scopes (such as fallback error messages, diagnostic information, or dynamic internal states) is leaked directly to the attacker.
This bypass occurs completely outside the standard request lifecycle, neutralizing all protective middlewares and hooks like JWT verification or session checks. The Common Vulnerability Scoring System (CVSS) v3.1 score is evaluated at 7.5 (High), with a vector of CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N. Confidentiality is highly impacted, while integrity and availability are unaffected.
The recommended remediation is upgrading the Fastify dependency to version 5.12.2 or later. This release enforces early fail-closed behavior for malformed URL inputs, preventing routing logic from triggering encapsulated 404 handlers.
If upgrading is not immediately feasible, developers can employ external controls to mitigate risk. Configured reverse proxies (such as Nginx, HAProxy, or Cloudflare) can be updated to reject requests containing invalid percent-encoded sequences or malformed characters before they reach the Node.js application layer.
Additionally, developers should audit their code to ensure that custom 404 handlers do not output sensitive debugging data or execute critical business logic that assumes authorization checks have already been completed.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
fastify Fastify | >= 4.0.0, < 5.12.2 | 5.12.2 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-288 |
| Attack Vector | Network |
| CVSS Score | 7.5 (High) |
| Exploit Status | poc |
| KEV Status | No |
The application provides an alternate path or channel that does not require authentication, allowing access to resources that are intended to be protected.
An authorization bypass and path traversal vulnerability exists in the SiYuan knowledge workspace platform. The vulnerability is located in the '/api/file/getUniqueFilename' endpoint inside the 'github.com/siyuan-note/siyuan/kernel' package. Under default configurations, this route is exposed to users who satisfy basic authentication middleware checks, which includes anonymous readers in publish mode. By supplying unvalidated absolute paths, remote attackers can verify the existence of files and directories across the host operating system, establishing a high-fidelity file existence oracle.
A highly critical Regular Expression Denial of Service (ReDoS) vulnerability in basic-ftp, an FTP client library for Node.js. In versions prior to 6.2.1, a malicious or compromised FTP server can exploit this vulnerability to force the FTP client to consume quadratic CPU time during directory parsing. This issue blocks the single-threaded Node.js event loop, freezing the application process and leading to a complete Denial of Service (DoS).
An uncontrolled resource consumption vulnerability in the russh library allows remote authenticated attackers to exhaust server memory (heap) by flooding channel open requests during a stalled key re-exchange (rekeying) process, causing a denial of service via Out-of-Memory (OOM) termination.
A critical memory handling vulnerability exists in the pageant crate, a workspace component of the Rust-based russh SSH client library, during communication with the PuTTY Pageant SSH agent on Windows systems. Prior to version 0.2.3, the library's shared memory parsing logic blindly trusted a peer-controlled, 32-bit big-endian response length field. This allows local attackers running within the same user session to trigger out-of-bounds reads or execute an out-of-memory crash of the client application.
A validation bypass vulnerability exists in Fastify web framework prior to version 5.12.2. The flaw stems from shallow normalization of header validation schemas, which fails to lowercase nested or conditional schema rules (like JSON Schema dependencies or dependentRequired) defined in mixed or canonical casing. Consequently, because Node.js normalizes incoming HTTP request headers to lowercase, the compiled validator fails to match these headers against the un-normalized mixed-case schema triggers, silently skipping conditional checks and allowing unauthenticated attackers to bypass authorization or security headers.
CVE-2026-84469 is a high-severity request validation bypass vulnerability in the Fastify Node.js web framework. In versions prior to 5.12.2, Fastify uses loose truthiness checks to decide whether to compile request schemas. When a component (such as the body) is explicitly configured with a boolean 'false' schema—which under JSON Schema Draft 7 acts as a 'deny-all' constraint—Fastify's internal logic evaluates this as a falsy value and skips compilation entirely. This allows unauthenticated remote attackers to send arbitrary payloads to these endpoints, bypassing validation checks and directly executing backend route handlers.