# Remote process crash (OOM) via post‑serialization size check and large batch aggregation in JSON‑RPC

Monad JSON-RPC serializes full responses and batches before enforcing size caps, letting unauthenticated clients exhaust memory and crash the process.

- Payout: Contest reward
- Severity: medium
- Program: Monad
- Credited: RadiantLabs
- Disclosed: 2026-02-26
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2025-09-monad#m-03
- Library page: https://bugbountylibrary.com/r/c4%3A2025-09-monad%3AM-03
- Tags: domain:infra domain:web3 impact:dos kind:contest platform:code4rena sev:medium tech:rest technique:source-review vuln:dos

**Target:** JSON-RPC server (bft/monad-rpc handlers, eth_getLogs, eth_feeHistory)
**Root cause:** Response size cap is enforced only after the entire batch/response is serialized into a second RawValue, and batches are fully aggregated in memory before the check, duplicating peak allocation.
**Steps:**
1. Send a batch of up to 5000 requests (default batch_request_limit) each invoking eth_getLogs with wide filters producing ~200KB-1.5MB results.
2. Server runs each concurrently via join_all, collecting per-item pre-serialized Box<RawValue> results into a Vec<Response>.
3. Server then calls serde_json::value::to_raw_value(&response) to serialize the whole ResponseWrapper, duplicating the entire batch in memory.
4. Only after this second serialization is the max_response_size (25MB default) check applied, so peak allocation of many GB occurs before rejection.
5. Process is OOM-killed or thrashes, denying service. Alternatively a single eth_feeHistory with large block_count x reward_percentiles triggers the same late check.
**How found:** Code review of rpc_handler: noticed join_all batch aggregation into Vec<Response> with pre-serialized RawValues, then a second to_raw_value serialization before the length check; observed eth_getLogs lacks the permit-based limiter that eth_call/eth_estimateGas have, and CLI defaults allow 5000-item batches with 25MB cap.
**Exploitation:** Unauthenticated client sends one crafted batch of eth_getLogs requests (or a single large eth_feeHistory) to force multi-GB in-memory aggregation and double serialization before the size cap rejects, causing OOM termination of the RPC process.
**Insight:** When auditing RPC/API servers, check whether size limits are enforced before or after serialization and whether batch handlers aggregate all items in memory; endpoints lacking the concurrency limiter peers have (here eth_getLogs vs eth_call) are prime OOM amplification surfaces.
