Skip to main content

eventsource-encoder CVE-2026-44214

| EUVDEUVD-2026-31968 MEDIUM
Improper Neutralization of CRLF Sequences ('CRLF Injection') (CWE-93)
2026-05-08 https://github.com/rexxars/eventsource-encoder GHSA-m9g3-3g99-mhpx
5.3
CVSS 3.1 · NVD
Share

Severity by source

NVD PRIMARY
5.3 MEDIUM
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
vuln.today AI
4.0 MEDIUM

AC:H reflects the non-default application pattern required (attacker-controlled data must flow into event/id); S:C applies because the injected output affects the browser client; I:L for stream integrity spoofing with no confidentiality or availability impact.

3.1 AV:N/AC:H/PR:N/UI:N/S:C/C:N/I:L/A:N
4.0 AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:L/SA:N

Primary rating from NVD.

CVSS VectorNVD

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
Low
Availability
None

Lifecycle Timeline

4
CVSS changed
Jul 24, 2026 - 11:22 NVD
5.8 (MEDIUM) 5.3 (MEDIUM)
Source Code Evidence Fetched
Jul 23, 2026 - 22:44 vuln.today
Analysis Generated
Jul 23, 2026 - 22:44 vuln.today
CVE Published
May 08, 2026 - 20:49 nvd
MEDIUM 5.8

Blast Radius

ecosystem impact
† from your stack dependencies † transitive graph · vuln.today resolves 4-path depth
  • 10 npm packages depend on eventsource-encoder (2 direct, 8 indirect)

Ecosystem-wide dependent count for version 1.0.2.

DescriptionNVD

Summary

eventsource-encoder does not sanitize the event or id fields of an EventSourceMessage before serializing them. An attacker who controls either field can inject arbitrary Server-Sent Events line terminators (\n, \r, or \r\n) and thereby forge additional SSE fields or entire messages on the stream. This is similar in spirit to GHSA-4hxc-9384-m385 (h3), but the vulnerable fields are event/id rather than data/comment. These are less likely to be user-controllable, but should still be sanitized.

Details

In src/encode.ts, encodeMessage interpolates event and id into the output without inspecting them for line terminators:

ts
if (message.event) {
  output += `event: ${message.event}\n`
}
// ...
if (typeof message.id === 'string' || typeof message.id === 'number') {
  output += `id: ${message.id}\n`
}

The SSE specification treats \r, \n, and \r\n as line terminators. A \n (or \r) embedded in either field is rendered as the end of that field, allowing the rest of the input to be interpreted by the client as new SSE fields.

By contrast, data and comment already normalize all three line-terminator forms via NEWLINES_RE = /(\r\n|\r|\n)/g, so they are not affected.

Proof of concept

js
import {encode} from 'eventsource-encoder'

// Attacker-controlled value flows into `event`
const userSuppliedTopic = 'message\nevent: admin\ndata: {"role":"admin"}'

console.log(encode({event: userSuppliedTopic, data: 'hello'}))

Output:

event: message
event: admin
data: {"role":"admin"}
data: hello

The browser sees two events: a forged admin event with attacker-chosen payload, followed by the legitimate message event. The same primitive works through id for any string id value.

Impact

If untrusted input is passed into the event or id field of a message, an attacker can:

  • Spoof events of arbitrary type (rerouting payloads to handlers the attacker chooses)
  • Inject additional SSE fields (data:, id:, retry:) into the stream
  • Split a single encode() call into multiple distinct browser events
  • Override the client's Last-Event-ID via injected id: lines

The vulnerability requires that an application places attacker-controlled data into event or id. Applications that only put trusted, statically-defined values into these fields are not affected.

Patches

Fixed in eventsource-encoder@1.0.2. The event and string id fields are now validated; any value containing \r or \n causes the encoder to throw a TypeError rather than emit a malformed stream.

Workarounds

If users cannot upgrade, validate or strip line terminators from any untrusted value before passing it to encode / encodeMessage:

js
function safeSingleLine(value) {
  if (/[\r\n]/.test(value)) throw new Error('SSE field must be single-line')
  return value
}

encode({event: safeSingleLine(topic), id: safeSingleLine(id), data})

Resources

  • Related advisory (different package, same class): https://github.com/advisories/GHSA-4hxc-9384-m385
  • SSE spec, line terminators: https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream

Credit

Discovered while reviewing in light of GHSA-4hxc-9384-m385.

AnalysisAI

SSE field injection in eventsource-encoder below 1.0.2 allows an attacker who controls the event or id field values to inject line terminators into the serialized Server-Sent Events stream, forging additional SSE fields or entirely synthetic browser events. A working proof of concept is publicly documented in the GitHub Security Advisory GHSA-m9g3-3g99-mhpx, demonstrating that a crafted event value can cause the browser to receive a forged admin-typed event with attacker-chosen payload. No public exploit infrastructure has been identified and EPSS sits at the 1st percentile, reflecting the narrow application pattern required for exploitation.

Technical ContextAI

eventsource-encoder (pkg:npm/eventsource-encoder) is a TypeScript/JavaScript library for serializing Server-Sent Events messages on the server side. The SSE wire format, defined in the WHATWG HTML specification, treats \r, \n, and \r\n as line terminators that end a field; a bare newline in a field value therefore opens a new SSE field line. The root cause is CWE-93 (Improper Neutralization of CRLF Sequences): in src/encode.ts, the encodeMessage function performs direct template-literal interpolation of message.event and message.id without stripping or rejecting embedded line terminators. The library's data and comment fields are already protected via a NEWLINES_RE regex that normalises all three terminator forms, but this sanitisation was not applied to event or id. The affected package range is eventsource-encoder <= 1.0.1.

RemediationAI

Vendor-released patch: eventsource-encoder 1.0.2. Upgrade the npm dependency immediately - the fix causes encodeMessage to throw a TypeError when event or id contain \r or \n, converting a silent data-corruption risk into a loud, detectable error. Full advisory at https://github.com/rexxars/eventsource-encoder/security/advisories/GHSA-m9g3-3g99-mhpx. If upgrading is not immediately possible, add an application-layer guard before calling encode or encodeMessage: validate that the event and id values are single-line strings (i.e., reject any value matching /[\r\n]/) and throw before passing them to the library. This workaround mirrors what 1.0.2 does internally. The trade-off is that it moves the validation responsibility to each call site and must be applied consistently across all code paths that construct SSE messages.

Share

CVE-2026-44214 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy