# Nest: Remote process termination via a deeply nested microservice message pattern

Deeply nested pattern object in a NestJS TCP/RabbitMQ microservice message makes JSON.stringify throw RangeError, crashing the Node process.

- Payout: Research
- Severity: high
- Program: NestJS
- Found by: zerovulnlabs
- Disclosed: 2026-09-29
- CVE: CVE-2026-102281
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-m8vh-jmq9-5rjg
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-m8vh-jmq9-5rjg
- Tags: area:oss domain:oss impact:dos kind:research platform:ghsa sev:high tech:nodejs technique:parser-differential technique:source-review vuln:dos

**Target:** @nestjs/microservices TCP and RabbitMQ transports
**Root cause:** ServerTCP/ServerRMQ handleMessage call JSON.stringify on a client-supplied pattern object without a guard; JSON.parse accepts nesting deeper than JSON.stringify can recurse, so stringify throws RangeError. The rejection from handleMessage is unhandled, terminating the process under default --unhandled-rejections=throw.
**Steps:**
1. Build a deeply nested pattern as raw text: `'{"nested":'.repeat(100000) + '{}' + '}'.repeat(100000)`
2. Wrap into a message: `{"pattern":<pattern>,"data":null,"id":"1"}`
3. Connect to the TCP transport port (default 3001) and write Nest framing: `<byteLength>#<json>`
4. Server's JSON.stringify(packet.pattern) throws RangeError: Maximum call stack size exceeded; unhandled rejection kills the process
5. For RabbitMQ transport, publish the equivalent payload to the consumed queue/exchange
**How found:** Noticed the pattern was stringified without a guard and reasoned that JSON.parse accepts nesting depths JSON.stringify cannot re-serialize, since stringify recurses natively; crafted the payload as text rather than via JSON.stringify so it is serializable by the attacker but not the victim.
**Exploitation:** Attacker with network reach to the TCP port (no auth by default) or publish rights on the consumed RabbitMQ queue sends one crafted message; the server parses it, then crashes on re-serialization. One message per crash, repeatable.
**Insight:** Look for asymmetric parse/serialize pairs on attacker-controlled input: anything JSON.parse accepts but JSON.stringify chokes on (deep nesting) is a crash primitive, especially where the resulting rejection is unhandled in async handlers.

