Conversation
…T_LINE_BYTES constant (10 MB) and reject requests exceeding this limit before JSON parsing. This prevents memory exhaustion from malicious or buggy clients sending extremely large payloads. The check happens early in dispatch_request, returning a request_too_large error with a clear message about the size limit.
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
…ity fixes for CI audit failures: - Upgrade quinn-proto from 0.11.14 to 0.11.15 Fixes: RUSTSEC-2026-0185 - Remote memory exhaustion from unbounded out-of-order stream reassembly (severity 7.5 high) - Force form-data to ^4.0.6 via pnpm overrides Fixes: GHSA-hmw2-7cc7-3qxx - CRLF injection in form-data via unescaped multipart field names and filenames (severity high) Both vulnerabilities existed in main branch dependencies and are not introduced by this PR. Fixing them here to unblock CI checks.
This was referenced Jun 27, 2026
This was referenced Sep 3, 2026
Open
This was referenced Sep 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The daemon's request handling doesn't check incoming JSON line sizes before parsing. This creates a memory exhaustion vector where malicious or buggy clients can send arbitrarily large payloads and force the daemon to allocate huge buffers during deserialization.
The vulnerable path is in
dispatch_request():lines.next_line().await?orreader.lines()serde_json::from_str::<RequestEnvelope>(line)This is a local attack surface issue. The daemon runs as a trusted process, but nothing stops a compromised client or a bug in the CLI from sending multi-GB requests. On Windows, where TCP is the default transport, this is slightly worse because TCP doesn't have the same filesystem permission constraints as Unix sockets.
What This PR Does
Adds a size check before JSON parsing:
Requests over 10 MB get rejected with a clear error code and message. The check happens after the line is read but before
serde_jsontouches it, so we're still reading the full line into memory once, but we avoid the deserialization overhead and structured allocation that happens inside serde.Why 10 MB?
This is deliberately generous. Normal protocol requests are tiny:
MessageSendwith a reasonable prompt: <50 KBEventsSubscribe: <1 KBSessionCreate: <500 bytesEven a
MessageSendwith a 100,000-token context (way beyond typical usage) would still be under 1 MB as JSON. 10 MB gives us 10x headroom for weird edge cases while still preventing absurd payloads.If someone legitimately needs to send >10 MB requests, that's a protocol design issue, not a limit we should silently accommodate.
Trade-offs
Why not use a streaming JSON parser?
We could switch to something like
serde_json::Deserializer::from_reader()with a length-limited reader, but that's a bigger refactor. This PR is a targeted fix that addresses the immediate DoS vector without changing the protocol dispatch flow.Why not reject at the transport layer?
Tokio's
BufReaderalready buffers internally, so by the time we have a "line," we've already read it. We'd need to intercept at a lower level (customAsyncReadwrapper) to avoid the allocation entirely. That's possible but adds complexity. This approach is simpler: we read the line, check its size, and bail early if it's ridiculous.What about legitimate large payloads?
If we ever need chunked uploads, large file attachments, or streaming context, those should use a different protocol path (e.g., multipart protocol frames, separate file upload endpoint). The line-delimited JSON protocol isn't designed for that.
Validation
I ran the existing daemon manually and verified:
I couldn't run the full test suite due to linker issues on Windows, but the change is straightforward: size check before parse, early rejection if oversized. The logic doesn't touch any other daemon behavior.
Related Work
This complements existing security PRs:
Those address auth and credential leakage. This addresses resource exhaustion. Together they harden the daemon against local threats.
Next Steps
After this PR:
EventLog::append_eventFor now, this closes the immediate gap without requiring protocol changes or extensive refactoring.