#17678: fix(gateway): expose timeoutMs in readJsonBody to prevent Slowloris DoS
gateway
stale
size: S
Cluster:
Timeouts and Memory Management Fixes
## Summary
- **Problem:** `readJsonBody()` in `hooks.ts` did not expose the `timeoutMs` parameter, preventing callers from configuring the body read timeout for Slowloris DoS mitigation (CWE-400).
- **Why it matters:** While the underlying `readJsonBodyWithLimit()` enforces a 30s default timeout (added in 3cbcba10c), the `readJsonBody()` wrapper hid this parameter, making it impossible for callers to customize the timeout for their specific use case.
- **What changed:** Added optional `timeoutMs` parameter to `readJsonBody()` that passes through to `readJsonBodyWithLimit()`. Added 7 comprehensive tests covering timeout, size limits, race conditions, and connection close scenarios.
- **What did NOT change:** No changes to the HTTP server config, no new dependencies, no breaking signature changes. The default timeout (30s) remains unchanged.
## Change Type (select all)
- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Docs
- [x] Security hardening
- [ ] Chore/infra
## Scope (select all touched areas)
- [x] Gateway / orchestration
- [ ] Skills / tool execution
- [ ] Auth / tokens
- [ ] Memory / storage
- [ ] Integrations
- [ ] API / contracts
- [ ] UI / DX
- [ ] CI/CD / infra
## Linked Issue/PR
- Closes #5122
- Closes #6302
## User-visible / Behavior Changes
None. The default 30s timeout was already enforced by the lower layer. This change only exposes the parameter for callers who need to customize it.
## Security Impact (required)
- New permissions/capabilities? No
- Secrets/tokens handling changed? No
- New/changed network calls? No
- Command/tool execution surface changed? No
- Data access scope changed? No
## Repro + Verification
### Environment
- OS: Linux x86_64
- Runtime/container: Node.js v22.22.0
- Model/provider: N/A
- Integration/channel: Gateway webhooks
- Relevant config: Default hooks config
### Steps
1. Start gateway with hooks enabled
2. Send a slow POST to `/hooks/agent` (e.g., `curl --limit-rate 1 -X POST ...`)
3. Observe that the connection is terminated after 30s (default) or custom `timeoutMs`
### Expected
- Slow requests terminated after timeout with `{ ok: false, error: "request body timeout" }`
- Socket destroyed to free resources
### Actual
- Matches expected behavior
## Evidence
- [x] Failing test/log before + passing after
```
✓ src/gateway/hooks-read-body.test.ts (7 tests) 165ms
✓ src/infra/http-body.test.ts (8 tests) 21ms
✓ src/gateway/hooks.test.ts (15 tests) 5ms
✓ src/gateway/server-http.hooks-request-timeout.test.ts (1 test) 4ms
Test Files 4 passed (4)
Tests 31 passed (31)
```
## Human Verification (required)
- Verified scenarios: timeout fires on stalled request, normal reads complete without timeout, size limit still enforced, custom timeoutMs respected, no double-resolution race condition, connection close handled
- Edge cases checked: empty body, oversized body, slow trickle (Slowloris), connection close before end
- What I did **not** verify: Manual integration test with live gateway (verified via unit tests only)
## Compatibility / Migration
- Backward compatible? Yes — new parameter is optional with existing default
- Config/env changes? No
- Migration needed? No
## Failure Recovery (if this breaks)
- How to disable/revert: Revert this commit; the underlying timeout still applies via `readJsonBodyWithLimit` defaults
- Files/config to restore: `src/gateway/hooks.ts`
- Known bad symptoms: N/A — additive-only change
## Risks and Mitigations
None — this is a one-line parameter pass-through with tests.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Exposes optional `timeoutMs` parameter in `readJsonBody()` wrapper function to allow callers to customize Slowloris DoS protection timeout. The change is minimal (adding one optional parameter and passing it through to the underlying `readJsonBodyWithLimit()`) and maintains full backward compatibility since the default 30s timeout was already enforced at the lower layer.
- Added optional `timeoutMs` parameter to `readJsonBody()` function signature in `src/gateway/hooks.ts:177-180`
- Parameter correctly passed through to `readJsonBodyWithLimit()` call
- New test file `src/gateway/hooks-read-body.test.ts` with 7 tests covering timeout behavior, size limits, race conditions, and edge cases
- All existing callers remain unaffected since parameter is optional with existing default behavior
<h3>Confidence Score: 5/5</h3>
- Safe to merge with no risk - purely additive change with comprehensive test coverage
- Simple parameter pass-through that exposes existing functionality without changing default behavior. Backward compatible (optional parameter), well-tested (7 new tests covering timeouts, size limits, and edge cases), and addresses legitimate security concern (Slowloris DoS mitigation CWE-400). All existing callers verified to work without changes.
- No files require special attention
<sub>Last reviewed commit: 298ce7e</sub>
<!-- greptile_other_comments_section -->
<sub>(5/5) You can turn off certain types of comments like style [here](https://app.greptile.com/review/github)!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#6302: fix: Add timeouts to prevent indefinite hangs (issues #4954, #4956,...
by batumilove · 2026-02-01
78.5%
#5834: fix(line): add timeout and size limit to readRequestBody to prevent...
by hclsys · 2026-02-01
76.5%
#7615: fix(gateway): add request timeout to GatewayClient
by alamine42 · 2026-02-03
74.1%
#9114: Fix: Reduce NO_TIMEOUT_MS to 24 days to avoid Node.js overflow warning
by vishaltandale00 · 2026-02-04
73.1%
#12477: fix(agents): prevent TimeoutOverflowWarning when timeout is disabled
by skylarkoo7 · 2026-02-09
72.0%
#18221: fix(cli): raise cron command timeout to 90s and retry read-only RPCs
by BinHPdev · 2026-02-16
72.0%
#16963: fix: enable auth rate limiting by default
by StressTestor · 2026-02-15
71.5%
#22719: fix(agents): make subagent announce timeout configurable (restore 6...
by Valadon · 2026-02-21
71.0%
#20381: feat(gateway): make chat history byte limit configurable via `gatew...
by mgratch · 2026-02-18
71.0%
#23420: Gateway: tighten WS connect schema bounds and validation
by bmendonca3 · 2026-02-22
70.7%