feat(proxy): validate JSON-RPC frames in SSE event stream
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 2.2k
- Forks
- 300
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 184
Description
Background
PR #5288 adds upstream JSON-RPC response validation for the streamable-HTTP transport. SSE is explicitly out of scope because the fix architecture (buffer full body → validate → rewrite or pass through) doesn't work for a streaming event format.
The gap
When an SSE-based MCP upstream sends a structurally invalid JSON-RPC frame (data: line without jsonrpc:"2.0", wrong id type, etc.), the transparent proxy forwards it unchanged. Clients receive the malformed event and may crash, misparse it, or treat it as a legitimate response.
Why it's harder than streamable-HTTP
For streamable-HTTP, ProcessResponse buffers the entire HTTP response body before any bytes reach the client, so it can atomically reject and rewrite to 502.
For SSE:
- The
200 OKandContent-Type: text/event-streamheaders are committed before any events arrive. There is no way to rewrite the status code for a malformed event mid-stream. - A fix needs a per-event streaming interceptor that wraps the SSE body reader, parses each
data:line as it arrives, validates the JSON-RPC content, and either synthesizes an error event or closes the stream cleanly on the first invalid frame. - "Close the stream" is the strongest guarantee available — unlike streamable-HTTP, the proxy cannot return a structured 502 for an individual bad event.
Proposed scope
A follow-up to #5288 scoped to the SSE response processor:
- Wrap the SSE body reader with a per-event interceptor
- On an invalid
data:JSON-RPC frame: write a syntheticdata: {"jsonrpc":"2.0","id":null,"error":{"code":-32000,"message":"Invalid upstream JSON-RPC frame"}}\n\nevent and close the stream - Leave non-
data:SSE lines (comments,event:,retry:) untouched - The guarantee is weaker than streamable-HTTP (client receives the error event, not a 502) — document this explicitly
Context
Found via DAST adversarial testing (checkMalformedFraming in the enterprise DAST suite). The test currently documents this as a known finding for the SSE transport.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading PR #5288 and the existing ProcessResponse path to understand the streamable-HTTP validation architecture. Then inspect the SSE response processor and the checkMalformedFraming test in the enterprise DAST suite. Done means invalid data frames produce the specified synthetic error event and close the stream, while non-data SSE lines remain unchanged and the weaker guarantee is documented.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- backend, networking, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100