Skip to content

fix(gateway): cap proxy SSE buffer to prevent unbounded memory growth - #58622

Closed
AlexFucuson9 wants to merge 1 commit into
NousResearch:mainfrom
AlexFucuson9:alex/fix-sse-buffer-cap
Closed

AlexFucuson9 wants to merge 1 commit into
NousResearch:mainfrom
AlexFucuson9:alex/fix-sse-buffer-cap

Conversation

@AlexFucuson9

Copy link
Copy Markdown
Contributor

Summary

Gateway proxy mode parses SSE streams by appending chunks to a buffer and splitting on newlines. A malformed or boundary-less upstream can grow the buffer without limit, eventually OOMing the process.

Root Cause

In gateway/run.py::_run_agent_via_proxy, the successful SSE path:

buffer = ""
async for chunk in resp.content.iter_any():
    text = chunk.decode("utf-8", errors="replace")
    buffer += text
    while "\n" in buffer:
        line, buffer = buffer.split("\n", 1)

If the remote proxy sends a long malformed SSE line without a newline boundary, the residual buffer has no cap.

Fix

Add a 1 MiB cap on the residual buffer. If the buffer exceeds this without seeing a line boundary, raise RuntimeError to abort the proxy connection instead of continuing to accumulate.

Fixes #58471

Gateway proxy mode parses SSE streams by appending chunks to a buffer
and splitting on newlines. A malformed or boundary-less upstream can
grow the buffer without limit, eventually OOMing the process.

Add a 1 MiB cap on the residual buffer. If the buffer exceeds this
without seeing a line boundary, raise RuntimeError to abort the proxy
connection instead of continuing to accumulate.

Fixes NousResearch#58471
@alt-glitch alt-glitch added type/bug Something isn't working comp/gateway Gateway runner, session dispatch, delivery sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages P2 Medium — degraded but workaround exists duplicate This issue or pull request already exists labels Jul 5, 2026
@alt-glitch

Copy link
Copy Markdown

This was generated by AI during triage.
Duplicate of #58472 — both fix #58471 by capping the proxy-mode residual SSE buffer in gateway/run.py::_run_agent_via_proxy (same site, same mechanism; #58472 uses a 16 MiB cap, this uses 1 MiB). #58472 is earlier/canonical (by the issue author). Note the 3-PR salvage #58504 also carries this cap. Flagging for a maintainer to pick one.

@teknium1

Copy link
Copy Markdown
Collaborator

Thanks for identifying the unbounded residual-SSE-buffer failure mode. Automated hermes-sweeper review found that current main already implements this safeguard.

  • gateway/run.py:71 defines _GATEWAY_PROXY_SSE_BUFFER_MAX_CHARS at 16 MiB, and gateway/run.py:17140 rejects a residual proxy SSE buffer over that limit.
  • tests/gateway/test_proxy_mode.py:338 already covers a boundary-less stream and verifies the resulting proxy connection error.
  • This landed in 5b8593266f6e8847bfb536225cfb058f7de4fb74 (fix(gateway): cap proxy SSE line buffer), shipped in v2026.7.7.
  • This also matches the prior duplicate report noting that fix(gateway): cap proxy SSE line buffer #58472 was the canonical implementation.

Closing as implemented on main.

@teknium1 teknium1 closed this Jul 15, 2026
@teknium1 teknium1 added the sweeper:implemented-on-main Sweeper: behavior already present on current main label Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery duplicate This issue or pull request already exists P2 Medium — degraded but workaround exists sweeper:implemented-on-main Sweeper: behavior already present on current main sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gateway proxy SSE parser can buffer an unbounded boundary-less line

3 participants