Tier 2 per SECURITY.md — a compatibility-affecting change; needs maintainer approval before merge. Surfaced by the security review behind #39.
Problem
HttpDispatcher.send reads the entire response body with BodyHandlers.ofByteArray() (HttpDispatcher.java:81) — no size cap, no Content-Length sanity check. The §10 controls bound time (99s/2s), not bytes. The body is then amplified: tree-parsed into a JsonNode (2nd copy) and body().clone()'d in AbstractMarketDataResponse (3rd copy).
A hostile/misconfigured endpoint can stream a multi-GB body → process-wide OutOfMemoryError the consumer cannot catch or defend against.
Trigger: requires a compromised endpoint, a baseUrl pointed at an attacker, or MITM (defeated by TLS) — not reachable against the real API over HTTPS. Robustness/DoS hardening, not a remote 0-day.
Proposed fix (needs approval — Tier 2)
- Add a response-body size ceiling (a bounded
BodySubscriber that aborts past N bytes, and/or reject when Content-Length exceeds a limit), surfaced as a controlled ParseError/NetworkError.
- Separately, pin Jackson
StreamReadConstraints explicitly so a future Jackson downgrade below 2.15 can't silently re-open the long-number/long-string/deep-nesting DoS defaults we currently rely on.
Why Tier 2
A size ceiling is a new default limit that could reject unusually large but legitimate responses — needs a deliberate cap value.
Tier 2 per
SECURITY.md— a compatibility-affecting change; needs maintainer approval before merge. Surfaced by the security review behind #39.Problem
HttpDispatcher.sendreads the entire response body withBodyHandlers.ofByteArray()(HttpDispatcher.java:81) — no size cap, noContent-Lengthsanity check. The §10 controls bound time (99s/2s), not bytes. The body is then amplified: tree-parsed into aJsonNode(2nd copy) andbody().clone()'d inAbstractMarketDataResponse(3rd copy).A hostile/misconfigured endpoint can stream a multi-GB body → process-wide
OutOfMemoryErrorthe consumer cannot catch or defend against.Trigger: requires a compromised endpoint, a
baseUrlpointed at an attacker, or MITM (defeated by TLS) — not reachable against the real API over HTTPS. Robustness/DoS hardening, not a remote 0-day.Proposed fix (needs approval — Tier 2)
BodySubscriberthat aborts past N bytes, and/or reject whenContent-Lengthexceeds a limit), surfaced as a controlledParseError/NetworkError.StreamReadConstraintsexplicitly so a future Jackson downgrade below 2.15 can't silently re-open the long-number/long-string/deep-nesting DoS defaults we currently rely on.Why Tier 2
A size ceiling is a new default limit that could reject unusually large but legitimate responses — needs a deliberate cap value.