The server-side SSE serializer wrote the single-line fields event, id, and retry verbatim to the text/event-stream wire with no CR/LF filtering, and split the multi-line data field only on \n, ignoring a bare \r that is also a valid SSE line terminator. The SSEEvent constructor validated nothing. An application echoing attacker-influenced text into id/event/retry (for example a Last-Event-ID or correlation id) could embed CR/LF to forge additional SSE fields or a blank-line dispatch boundary, injecting complete events into every connected EventSource client.
SSE event injection: an attacker could forge or inject arbitrary events delivered to all connected EventSource clients.
Fixed in HTTP.jl v2.4.0. The SSEEvent keyword constructor rejects CR/LF in event/id (and NUL in id, and a negative retry), write(::SSEStream, ::SSEEvent) re-validates as defense-in-depth, and data is split on \r\n|\r|\n so all line-break forms normalize to separate data: lines with no raw CR on the wire.
Reported to the JuliaLang security team through Anthropic's Coordinated Vulnerability Disclosure program.
{
"license": "CC-BY-4.0"
}