{"id":"GHSA-fvjq-6m4v-mw3m","kind":"vulnerability","aliases":["GHSA-fvjq-6m4v-mw3m"],"related":[],"title":"Path-scoped middleware bypass on Fastify via absolute-form request targets with a query before the path","description":"| Field | Value |\n| --- | --- |\n| Ecosystem | npm |\n| Package | `@nestjs/platform-fastify` |\n| Affected versions | `< 11.2.9` and `>= 12.0.0, < 12.4.1` |\n| Patched versions | `11.2.9` and `12.4.1` |\n| Severity | High |\n| CVSS v3.1 | `AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N` (8.1) |\n| CWE | CWE-436 (Interpretation Conflict), CWE-288 (Authentication Bypass Using an Alternate Path or Channel) |\n\n### Summary\n\nOn the Fastify adapter, a request whose absolute-form request target places a query string between the authority and\nthe path could reach a route handler without running the path-scoped Nest middleware bound to that route. Applications\nthat enforce authentication or authorization in middleware could run the protected handler with those checks skipped.\nThis completes the fix for [GHSA-9c5c-9qcx-q35q](https://github.com/nestjs/nest/security/advisories/GHSA-9c5c-9qcx-q35q).\n\n### Impact\n\nAn application is affected if it uses `@nestjs/platform-fastify`, binds middleware to specific paths with\n`MiddlewareConsumer.forRoutes(...)` or `.exclude(...)`, and is reachable by clients that control the raw request line.\n\n- **11.x:** affected with the dependencies 11.2.x installs by default.\n- **12.x:** a default install is not affected, because the router bundled with current `fastify` versions resolves such\n  targets the same way the middleware does. Applications that pin an older `fastify` or `find-my-way` are affected.\n\nA reverse proxy that rewrites request targets to origin-form before they reach the application prevents the issue.\n\n### Details\n\nThe adapter and the router derived the path of such a target in different ways, so the middleware was matched against\na different path than the one the router dispatched to.\n\n### Patches\n\nFixed in **11.2.9** and **12.4.1**. The adapter now derives the path the same way current router versions do, and a\ntarget it can't resolve unambiguously is answered with 404 on every router version.\n\n### Workarounds\n\n- Forward only origin-form request targets to the application, for example through a reverse proxy.\n- On 12.x, use `fastify` 5.12.8 or later.\n- Enforce authentication and authorization in guards, which run for the matched route, rather than in middleware.\n\n### Credit\n\nReported by Salih Caglar Ispirli.","summary":"The NestJS Fastify adapter can match path-scoped middleware against a different path than the router dispatches to, when a request target places a query string before the path. An attacker can reach a protected route handler without the authentication or authorization middleware running.","severity":"high","cvss":null,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"@nestjs/platform-fastify","fixed":["12.4.1"],"affected":">= 12.0.0, < 12.4.1","ecosystem":"npm"},{"name":"@nestjs/platform-fastify","fixed":["11.2.9"],"affected":"< 11.2.9","ecosystem":"npm"}],"ecosystems":["npm"],"tags":["cwe-288","cwe-436","fastify","nestjs","node","package","self-hosted"],"not_affected_if":["auth-in-guards","default-fastify-12","origin-form-proxy"],"how_to_check":"- Run `npm ls @nestjs/platform-fastify` to see the installed version.\n- Check whether the app uses `MiddlewareConsumer.forRoutes(...)` or `.exclude(...)` for auth checks.\n- For 12.x, run `npm ls fastify` and `npm ls find-my-way` to see whether an older router is pinned.\n- Check whether a reverse proxy forwards absolute-form request targets to the app.","fix":"- `@nestjs/platform-fastify` `11.2.9` for the 11.x line\n- `@nestjs/platform-fastify` `12.4.1` for the 12.x line\n- On 12.x, `fastify` `5.12.8` or later, per the workarounds","status":"open","published_at":"2026-11-12T13:53:55+00:00","first_seen_at":"2026-11-12T13:56:25+00:00","triaged_at":"2026-11-12T13:57:24+00:00","updated_at":"2026-11-12T13:57:24+00:00","category":"package","confidence":0.85,"triage":{"at":"2026-11-12T13:57:24Z","model":"claude-haiku-5-5","output":{"fix":"- `@nestjs/platform-fastify` `11.2.9` for the 11.x line\n- `@nestjs/platform-fastify` `12.4.1` for the 12.x line\n- On 12.x, `fastify` `5.12.8` or later, per the workarounds","reach":"internet","title":"NestJS Fastify adapter: path middleware skipped by crafted absolute-form request targets","impact":"high","summary":"The NestJS Fastify adapter can match path-scoped middleware against a different path than the router dispatches to, when a request target places a query string before the path. An attacker can reach a protected route handler without the authentication or authorization middleware running.","audience":"businesses","category":"package","nicknames":[],"who_cares":["nestjs","fastify","node","self-hosted"],"confidence":0.85,"fix_status":"available","needs_auth":"no","worst_case":"Protected route handlers run without auth middleware checks","analyst_note":"","how_to_check":"- Run `npm ls @nestjs/platform-fastify` to see the installed version.\n- Check whether the app uses `MiddlewareConsumer.forRoutes(...)` or `.exclude(...)` for auth checks.\n- For 12.x, run `npm ls fastify` and `npm ls find-my-way` to see whether an older router is pinned.\n- Check whether a reverse proxy forwards absolute-form request targets to the app.","plain_action":"","product_name":"","needs_analyst":false,"not_affected_if":["origin-form-proxy","auth-in-guards","default-fastify-12"],"who_is_affected":"Applications that run NestJS on the Fastify adapter, enforce auth in path-scoped middleware, and accept requests from clients that control the raw request line. A default 12.x install with current fastify is not affected; 11.2.x installs and apps that pin an older fastify or find-my-way are. A reverse proxy that rewrites targets to origin-form prevents it.","user_interaction":"no","product_ecosystem":"","needs_special_setup":"yes","severity_if_unknown":"high"},"cost_usd":0.000892,"input_tokens":5428,"output_tokens":698,"severity_before":"high"},"analyst_status":null,"analyst_note":null,"search":"'-288':33B,125C '-436':35B,121C '/nestjs/nest/security/advisories/ghsa-9c5c-9qcx-q35q).':203C '11':233C '11.2':239C '11.2.9':96C,102C,336C '12':244C,386C '12.0.0':98C '12.4.1':99C,104C,338C '404':363C '5.12.8':390C '6m4v':23A,28A '8.1':118C '9c5c':198C '9qcx':199C 'absolut':10A,143C 'absolute-form':9A,142C 'adapt':46B,138C,303C,340C 'affect':94C,208C,235C,251C,281C 'altern':130C 'answer':361C 'applic':174C,206C,269C,297C,378C 'attack':74B 'authent':83B,126C,177C,394C 'author':85B,153C,179C,396C 'av':109C 'bind':213C 'bound':170C 'bundl':255C 'bypass':5A,127C 'caglar':413C 'channel':133C 'check':189C 'client':226C 'complet':192C 'conflict':123C 'control':228C 'could':157C,182C 'credit':409C 'current':257C,348C 'cvss':107C 'cwe':32B,34B,119C,120C,124C 'default':243C,247C 'depend':238C 'deriv':307C,342C 'detail':301C 'differ':55B,315C,324C 'dispatch':60B,331C 'ecosystem':90C 'enforc':176C,393C 'everi':365C 'exampl':380C 'exclud':221C 'fastifi':7A,36B,45B,137C,258C,274C,389C 'field':88C 'find':277C 'find-my-way':276C 'fix':194C,334C 'form':11A,144C,292C,373C 'forward':369C 'fvjq':22A,27A 'ghsa':21A,26A,197C 'ghsa-9c5c-9qcx-q35q':196C 'ghsa-fvjq-6m4v-mw3m':20A,25A 'github.com':202C 'github.com/nestjs/nest/security/advisories/ghsa-9c5c-9qcx-q35q).':201C 'guard':398C 'h/a':116C 'h/i':115C 'h/pr':111C 'handler':80B,161C,186C 'high':106C 'host':42B 'impact':204C 'instal':241C,248C 'interpret':122C 'ispir':414C 'issu':300C 'later':392C 'line':232C 'match':48B,321C,403C 'middlewar':4A,52B,86B,169C,181C,214C,267C,319C,408C 'middlewareconsumer.forroutes':219C 'mw3m':24A,29A 'n':117C 'n/ac':110C 'n/s':113C 'n/ui':112C 'nest':168C 'nestj':37B,44B 'nestjs/platform-fastify':30A,31A,93C,212C 'node':38B 'npm':91C 'older':273C 'one':328C 'origin':291C,372C 'origin-form':290C,371C 'packag':39B,92C 'patch':100C,333C 'path':2A,19A,50B,56B,72B,131C,156C,166C,217C,309C,325C,344C 'path-scop':1A,49B,165C 'pin':271C 'place':66B,147C 'prevent':298C 'protect':78B,185C 'proxi':284C,384C 'q35q':200C 'queri':16A,68B,149C 'rather':405C 'raw':230C 'reach':76B,158C,295C 'reachabl':224C 'report':410C 'request':12A,64B,140C,145C,231C,287C,374C 'resolv':260C,358C 'revers':283C,383C 'rewrit':286C 'rout':79B,160C,173C,404C 'router':59B,254C,306C,330C,349C,366C 'run':87B,163C,183C,400C 'salih':412C 'scope':3A,51B,167C 'self':41B 'self-host':40B 'sever':105C 'skip':190C 'specif':216C 'string':69B,150C 'summari':134C 'target':13A,65B,146C,262C,288C,313C,354C,375C 'u/c':114C 'unambigu':359C 'use':128C,211C,388C 'v3.1':108C 'valu':89C 'version':95C,101C,259C,350C,367C 'via':8A 'way':265C,279C,316C,347C 'whose':141C 'without':81B,162C 'workaround':368C 'x':234C,240C,245C,387C","nicknames":[],"mitigations":[],"who_affected":"Applications that run NestJS on the Fastify adapter, enforce auth in path-scoped middleware, and accept requests from clients that control the raw request line. A default 12.x install with current fastify is not affected; 11.2.x installs and apps that pin an older fastify or find-my-way are. A reverse proxy that rewrites targets to origin-form prevents it.","tier":"B","verified":{},"analyst_revisit_at":null,"fix_status":"available","audience":"businesses","plain_action":null,"pkeys":["platformfastify"],"ptokens":["fastify","nestjs","platform"],"labels":["cwe288","cwe436","fastify","high","nestjs","node","npm","package","selfhosted"],"campaign_type":null,"search_a":"'6m4v':23A,28A 'absolut':10A 'absolute-form':9A 'bypass':5A 'fastifi':7A 'form':11A 'fvjq':22A,27A 'ghsa':21A,26A 'ghsa-fvjq-6m4v-mw3m':20A,25A 'middlewar':4A 'mw3m':24A,29A 'nestjs/platform-fastify':30A,31A 'path':2A,19A 'path-scop':1A 'queri':16A 'request':12A 'scope':3A 'target':13A 'via':8A","search_b":"'-288':33B '-436':35B 'adapt':46B 'attack':74B 'authent':83B 'author':85B 'cwe':32B,34B 'differ':55B 'dispatch':60B 'fastifi':36B,45B 'handler':80B 'host':42B 'match':48B 'middlewar':52B,86B 'nestj':37B,44B 'node':38B 'packag':39B 'path':50B,56B,72B 'path-scop':49B 'place':66B 'protect':78B 'queri':68B 'reach':76B 'request':64B 'rout':79B 'router':59B 'run':87B 'scope':51B 'self':41B 'self-host':40B 'string':69B 'target':65B 'without':81B","search_c":"'-288':125C '-436':121C '/nestjs/nest/security/advisories/ghsa-9c5c-9qcx-q35q).':203C '11':233C '11.2':239C '11.2.9':96C,102C,336C '12':244C,386C '12.0.0':98C '12.4.1':99C,104C,338C '404':363C '5.12.8':390C '8.1':118C '9c5c':198C '9qcx':199C 'absolut':143C 'absolute-form':142C 'adapt':138C,303C,340C 'affect':94C,208C,235C,251C,281C 'altern':130C 'answer':361C 'applic':174C,206C,269C,297C,378C 'authent':126C,177C,394C 'author':153C,179C,396C 'av':109C 'bind':213C 'bound':170C 'bundl':255C 'bypass':127C 'caglar':413C 'channel':133C 'check':189C 'client':226C 'complet':192C 'conflict':123C 'control':228C 'could':157C,182C 'credit':409C 'current':257C,348C 'cvss':107C 'cwe':119C,120C,124C 'default':243C,247C 'depend':238C 'deriv':307C,342C 'detail':301C 'differ':315C,324C 'dispatch':331C 'ecosystem':90C 'enforc':176C,393C 'everi':365C 'exampl':380C 'exclud':221C 'fastifi':137C,258C,274C,389C 'field':88C 'find':277C 'find-my-way':276C 'fix':194C,334C 'form':144C,292C,373C 'forward':369C 'ghsa':197C 'ghsa-9c5c-9qcx-q35q':196C 'github.com':202C 'github.com/nestjs/nest/security/advisories/ghsa-9c5c-9qcx-q35q).':201C 'guard':398C 'h/a':116C 'h/i':115C 'h/pr':111C 'handler':161C,186C 'high':106C 'impact':204C 'instal':241C,248C 'interpret':122C 'ispir':414C 'issu':300C 'later':392C 'line':232C 'match':321C,403C 'middlewar':169C,181C,214C,267C,319C,408C 'middlewareconsumer.forroutes':219C 'n':117C 'n/ac':110C 'n/s':113C 'n/ui':112C 'nest':168C 'nestjs/platform-fastify':93C,212C 'npm':91C 'older':273C 'one':328C 'origin':291C,372C 'origin-form':290C,371C 'packag':92C 'patch':100C,333C 'path':131C,156C,166C,217C,309C,325C,344C 'path-scop':165C 'pin':271C 'place':147C 'prevent':298C 'protect':185C 'proxi':284C,384C 'q35q':200C 'queri':149C 'rather':405C 'raw':230C 'reach':158C,295C 'reachabl':224C 'report':410C 'request':140C,145C,231C,287C,374C 'resolv':260C,358C 'revers':283C,383C 'rewrit':286C 'rout':160C,173C,404C 'router':254C,306C,330C,349C,366C 'run':163C,183C,400C 'salih':412C 'scope':167C 'sever':105C 'skip':190C 'specif':216C 'string':150C 'summari':134C 'target':146C,262C,288C,313C,354C,375C 'u/c':114C 'unambigu':359C 'use':128C,211C,388C 'v3.1':108C 'valu':89C 'version':95C,101C,259C,350C,367C 'way':265C,279C,316C,347C 'whose':141C 'without':162C 'workaround':368C 'x':234C,240C,245C,387C","cause_entry":null,"cause_path":null,"disclosures_checked_at":null,"first_public_at":"2026-11-12T13:53:55+00:00","kev":null,"cvss_vector":null,"cvss_by":null,"poc_count":0,"sources":[{"source":"ghsa-repo","external_id":"GHSA-fvjq-6m4v-mw3m","url":"https://github.com/nestjs/nest/security/advisories/GHSA-fvjq-6m4v-mw3m","severity":"high","published_at":"2026-11-12T13:53:55+00:00","modified_at":"2026-11-12T13:53:55+00:00","first_seen_at":"2026-11-12T13:56:25+00:00","fetched_at":"2026-11-12T13:56:25+00:00","note":null}],"documents":[{"id":135293,"url":"https://github.com/nestjs/nest/security/advisories/GHSA-fvjq-6m4v-mw3m","title":"Maintainer's advisory: github.com","kind":"vendor","source":"ghsa-repo","publisher":"vendor","text":null,"published_at":null,"relation":"advisory","confidence":null,"note":"Maintainer's advisory: github.com"}],"disclosures":[],"exploit_sources":[],"notice":"Free to read, with fair use of about 60 pages a minute. For higher limits or API access: sales@infrastack.ai"}