Listen to this Post
The vulnerability in sse-channel arises from improper neutralization of special elements used in Server-Sent Events (SSE) output. The SSE protocol, defined in the WHATWG HTML specification, relies on newline characters (\n and \r) as field delimiters and double newlines (\n\n) as event separators. In versions of sse-channel prior to v4.0.1, the event, retry, and `id` fields were not sanitized for these control characters. An attacker who can control user-provided data passed into these fields can inject newlines, thereby breaking the intended structure of a single SSE event.
For example, after processing a message with an unsanitized `event` field containing "user\nid: injected\n\n", the library would generate an output stream containing "event: user\nid: injected\n\n". The `EventSource` API on the client side would parse this as two separate events: the first with the event type `”user”` and the second an entirely new event with ID "injected". Similarly, injecting a carriage return (\r) can be used to bypass filtering that only checks for \n. The root cause is the lack of a simple `replace(/\r?\n/g, ”)` on user input before embedding it into the SSE response buffer.
An attacker can trivially craft malicious payloads through any input vector that ultimately controls these message fields. Once processed, the injected event can be of any type, including those reserved for internal use (e.g., "error"), and can carry arbitrary data. Since the `EventSource` API processes events as they arrive, a successful injection leads to immediate, client-side execution of the event’s JavaScript handler, without any additional validation. The vulnerable code path is present in `SseChannel.prototype.send()` and SseChannel.prototype.broadcast(), where the internal `formatEventStreamMessage()` function concatenates strings without escaping or stripping control characters.
The patch in v4.0.1 adds a comprehensive sanitization step that strips all newline and carriage return characters from the event, retry, and `id` fields before formatting each message. This ensures that the integrity of the SSE stream boundaries cannot be violated by user-controlled data.
DailyCVE form:
Platform: sse-channel Node.js
Version: Before v4.0.1
Vulnerability: Unsanitized field injection
Severity: Moderate
date: 2026-04-27
Prediction: Patch 2026-05-05
—
What Undercode Say:
Analytics from the Undercode blog show that the lack of newline sanitization in SSE libraries is a recurring pattern. Below are commands and a Node.js test to audit and mitigate the issue.
Check installed version of sse-channel
npm list sse-channel
Exploit simulation: Connect to a vulnerable endpoint that reflects 'event' parameter
curl -X POST https://victim.com/api/stream -H "Content-Type: application/json" -d '{"event": "user\nid: 1337\n\ndata: Hacked\n\n"}'
Patch application
npm update sse-channel
// Vulnerable usage example (pre-v4.0.1)
const SseChannel = require('sse-channel');
let channel = new SseChannel();
channel.send('example_event', 'user-provided-id', 'Hello');
// After patching to v4.0.1, the same input would be sanitized:
channel.send('example_event', 'user-provided-id', 'Hello');
// The 'user-provided-id' is now stripped of any \r or \n characters.
Exploit:
An attacker injects newline characters into the event, retry, or `id` fields. For instance, sending a message with `event: “custom\nevent: injected\ndata: pwned”` causes the SSE stream to split. The browser’s `EventSource` will fire two separate `message` events: one for “custom” and another for “injected” with the data “pwned”. This allows arbitrary event spoofing, potentially hijacking application logic that relies on specific event types.
Protection from this CVE:
- Upgrade to sse-channel version 4.0.1 or later.
- If immediate upgrade is not possible, sanitize all user-controlled input passed to the
event,retry, or `id` fields by stripping newline (\n) and carriage return (\r) characters. - Implement a strong Content Security Policy (CSP) that restricts the sources from which `EventSource` can connect.
- Validate all event names and IDs against an allowlist of expected values on the server side before passing them to the SSE channel.
Impact:
- Event Spoofing: Attackers can inject arbitrary SSE events, including those not intended by the server.
- Client-side Manipulation: Injected events can cause frontend JavaScript `EventSource` listeners to execute unintended actions.
- Data Integrity: Consumers of the SSE stream cannot distinguish between legitimate server-originated events and attacker-injected ones, leading to data corruption or misinformation.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

