Originally published at HOL
An unauthenticated request with a malformed URL can skip Fastify not-found auth and land in a private sibling plugin fallback. When the request method has no matching route, Fastify internal not-found router used to dispatch bad URLs through a single shared handler pointer before URL decoding. That ignored plugin prefixes and skipped the preHandler declared on setNotFoundHandler. A public prefix could therefore reach a private not-found handler and read its full response. About 12.6 million weekly downloads for the fastify package.
OpenJS shipped the fix in fastify 5.12.2 on 2026-09-04 as a clustered security release. The lead advisory is GHSA-p68q-wchp-6fh7 (CVE-2026-76169). The same tag also closes CVE-2026-84469, CVE-2026-84428, and CVE-2026-84504.
What breaks
Encapsulated apps that put auth on a custom not-found handler under a private prefix are the blast radius for CVE-2026-76169. A malformed target under an unrelated public prefix could invoke the private fallback without that auth hook. The GHSA rates this High (CVSS 7.5), network, no privileges, no user interaction. Confidentiality impact is whatever that protected fallback returned.
The v5.12.1 to v5.12.2 patch is specific. In lib/four-oh-four.js Fastify removes the shared _routeEventHandler pointer and wires onBadUrl / onMaxParamLength to routerOptions, so malformed URLs fail closed before any application not-found handler runs.
setContext switches from an Object.assign shallow snapshot to an Object.create prototype link so preHandler hooks populated during preReady are not lost (covered in test/404s.test.js).
Same release, three sibling fixes:
- CVE-2026-84469 (GHSA-hwr6-493r-vm6h):
lib/route.jsandlib/schemas.jstreat schema presence with!== undefined, so a booleanfalseschema still installs validation instead of being treated as missing. - CVE-2026-84428 (GHSA-9q9j-q6p8-xq58):
lib/validation.jsadds recursivelowerCaseHeadersSchemacoveringdependencies,dependentRequired, anddependentSchemas, and emitsFSTSEC002when an external$refheader schema cannot be case-normalized. - CVE-2026-84504 (GHSA-667r-xxjv-c9mm): async validators no longer unwrap a resolved
{value, error}object the way sync compilers do, so a payload cannot replace the request part through those keys.
Who is not in scope
- Apps already on fastify 5.12.2 or later.
- Apps that never call
setNotFoundHandlerwith auth-gated private fallbacks (CVE-2026-76169 specifically). - Apps that reject malformed request targets at an upstream proxy or gateway before they reach Fastify.
- Fastify 3.x and earlier (advisories start at >= 4.0.0).
- @fastify/middie absolute-form path-scoped auth issues (that is CVE-2026-85184, a different package).
How to check
From the app root list the fastify package version.
npm ls fastify
If the installed version is from 4.0.0 up to but not including 5.12.2, you are in range for this release. Then search for custom not-found handlers that attach auth.
rg -n setNotFoundHandler
Any setNotFoundHandler that returns protected data or registers a preHandler under a private prefix is the CVE-2026-76169 pattern. Also review header schemas that use Draft-7 dependencies / Draft 2019-09 dependent keywords, boolean false schemas, and async custom validators.
How to fix
Upgrade fastify to 5.12.2 or later. That single bump closes all four advisories in this cluster.
npm install fastify@5.12.2
If you cannot upgrade immediately for CVE-2026-76169, reject malformed request targets before they reach the app and do not serve protected data from a not-found handler. A global onRequest auth hook does not mitigate the malformed-URL path, because that path skipped it.
What this is not
This is not remote code execution, not a default-install worm, and not the @fastify/middie absolute-form middleware bypass tracked as CVE-2026-85184. CVE-2026-76169 is an unauthenticated not-found / prefix-encapsulation auth bypass in Fastify core. The siblings are validation correctness bugs in the same 5.12.2 tag, not a separate middie story.
Top comments (0)