fix: absolute-form middleware bypass (fastify) and unserializable pattern crash (microservices) - #17737
Merged
Conversation
Requests using an absolute-form request target ("GET http://host/path")
were routed to the handler by Fastify while path-scoped middleware, which
matched against the raw request target, never ran.
- replace the inlined @fastify/middie fork with the upstream package
(9.3.4), which resolves absolute-form targets before matching and
already contains the decoded-path fix the fork was carrying
- resolve absolute-form targets in the adapter's own route check
- fold the deprecated top-level Fastify router options into
"routerOptions" so that @fastify/middie normalizes request paths the
same way the router does
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
"JSON.stringify" throws a RangeError for deeply nested message patterns. The TCP and RMQ servers stringified client-controlled patterns without guarding against it, and the resulting unhandled promise rejection terminated the process. Patterns are now stringified safely (falling back to a sentinel that matches no handler) and rejected message handling is routed to "handleError" instead of being left unhandled. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
12 tasks
kamilmysliwiec
pushed a commit
that referenced
this pull request
Sep 17, 2026
…17785) follow-up to #17737, which routed the tcp and rmq handleMessage rejections to handleError bcs an unhandled promise rejection terminates the process the mqtt, nats and redis servers hand the same async handleMessage to their client libraries with no catch, so the identical rejections still escape: mqtt.js and node-redis get the handler through an EventEmitter listener and nats.js calls the subscription callback without awaiting it, so a malformed packet that throws in the deserializer, or a handler that rejects, kills the whole process the three handlers now route rejections through handleError like tcp and rmq already do, so a bad packet logs an error instead of crashing the server
12 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR Checklist
PR Type
What is the current behavior?
@nestjs/platform-fastify: a request with an absolute-form request target (GET http://host/path HTTP/1.1) is routed to the handler by the Fastify router, but path-scoped middleware never runs, because the middleware engine matches against the raw request target. The inlined@fastify/middiefork in this repo was affected by the same issue as upstream (GHSA-hx87-8wv7-pjv8), which upstream fixed in 9.3.4.@nestjs/microservices: the TCP and RMQ servers stringify client-controlled message patterns withJSON.stringify, which throws aRangeErrorfor deeply nested objects. The resulting unhandled promise rejection terminates the process.What is the new behavior?
@nestjs/platform-fastify@fastify/middie@9.3.4package, which resolves absolute-form targets before matching and already contains the decoded-path fix the fork was carrying.find-my-way).ignoreTrailingSlash,ignoreDuplicateSlashes,caseSensitive, ...) are folded intorouterOptions. The adapter always passesrouterOptions(for the version constraint), and in that case Fastify only reflects the top-level values in the router itself, not ininitialConfig.routerOptions, which@fastify/middierelies on.fastify-pluginandreusifyare no longer direct dependencies of the package (they were only used by the fork).@nestjs/microservicesServer#getPatternAsString, falling back to a sentinel that matches no handler, so such requests get the regularNO_MESSAGE_HANDLERresponse (or nack) instead of crashing the process.handleMessagein the TCP and RMQ servers are routed tohandleErrorinstead of being left as unhandled rejections.Regression tests were added for both (raw-socket e2e test for the absolute-form target, unit tests for the deeply nested patterns and the rejection handling).
Does this PR introduce a breaking change?
🤖 Generated with Claude Code