fix(proxy): bound SSE parser buffer to prevent OOM#96993
fix(proxy): bound SSE parser buffer to prevent OOM#96993wangmiao0668000666 wants to merge 2 commits into
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 26, 2026, 5:11 AM ET / 09:11 UTC. Summary PR surface: Source +10, Tests +56. Total +66 across 2 files. Reproducibility: yes. Current main has a clear source path where Review metrics: 1 noteworthy metric.
Stored data model Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land this tail-buffer guard if maintainers accept the 64 KiB single-line boundary, and handle total proxy stream size through the related shared byte-guard path. Do we have a high-confidence way to reproduce the issue? Yes. Current main has a clear source path where Is this the best way to solve the issue? Yes for the parser-tail OOM vector. The latest PR head applies the cap after draining complete lines, which is the narrow maintainable fix; the separate total-body byte cap remains related follow-up work. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against ec737ee74d9b. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +10, Tests +56. Total +66 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
|
@clawsweeper re-review P1 finding addressed:
Commit: 501c07a |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
closing this as not mergeable in its current shape. the 64 KiB guard is not a valid proxy protocol limit: |
Extend the byte-accurate 1 MiB policy to the unterminated tail (data after last \n) and the EOF final frame, closing the bypass paths identified by ClawSweeper review. The 1 MiB tail cap is deterministic unlike the prior 64 KiB attempt (openclaw#96993) because any hostile payload exceeding 1 MiB total bytes triggers the cap regardless of TCP chunking. - Add tail buffer cap after draining complete lines (proxy.ts:237) - Add EOF final frame cap before processSseLine (proxy.ts:246) - 2 new tests: unterminated tail across chunks, no-newline EOF frame Co-Authored-By: Claude <[email protected]>
What Problem This Solves
The
streamProxySSE reader insrc/agents/runtime/proxy.ts:231accumulates decoded chunks into an internalbufferstring that only shrinks when a\nline boundary is found. If a hostile or misconfigured proxy endpoint sends data without newline delimiters, the buffer grows unboundedly — the same OOM vector fixed for the OpenAIparseSSEin #96972.This affects every LLM call routed through the OpenClaw runtime proxy gateway.
Changes
src/agents/runtime/proxy.ts(+10 LoC): AddedPROXY_SSE_BUFFER_MAX_BYTES = 64 KiBconstant. After each chunk decode, the buffer check throws an error if the accumulated buffer exceeds the cap — preventing unbounded memory growth. Mirrors theparseSSEfix in fix(openai): bound SSE parser buffer to prevent OOM #96972 exactly.src/agents/runtime/proxy.test.ts(+27 LoC): Added inline test"rejects oversized SSE response without line boundary in proxy reader"— 65 KiB proxy SSE response without\n→ buffer cap error.Real behavior proof
pnpm test src/agents/runtime/proxy.test.ts --runnode:httpserver delivering 65 KiB SSE without\n→ reader throws buffer cap error at 64 KiB. Server-side bytes-sent: 65.0 KiB.data: {"type":"done","reason":"stop"}\n\n) → passes through correctly.Out of scope
createSseByteGuard). That PR and this one are complementary — fix(runtime/proxy): bound streaming success-body SSE reads at 16 MiB #96768 caps total bytes, this PR caps the per-frame accumulation.Risk
Low. The cap (64 KiB) is well above any reasonable proxy event payload. If triggered, the stream errors with a clear message rather than silently terminating. The change is additive — no existing behavior is modified, only a guard added.
AI-assisted; reviewed before submission.