Skip to content

ServerSentEvent.toString allows field injection via line terminators in eventType, id and data #480

Description

@magdzikk

ServerSentEvent.toString interpolates eventType and id directly, and splits data on \n only. Since the WhatWG specification treats a CRLF pair, a lone LF and a lone CR as line terminators, a value containing any of these ends the current line on the wire, and the remainder is parsed by the client as a new field.

Current behaviour

ServerSentEvent(eventType = Some("a\ndata: x")).toString
// event: a
// data: x        <- injected data field

ServerSentEvent(id = Some("a\ndata: x")).toString
// id: a
// data: x        <- injected data field

ServerSentEvent(data = Some("x\revent: foo")).toString
// data: x\revent: foo   <- a client splitting on CR sees an injected event field

eventType and id are the more exposed of the three: they are interpolated with no splitting or validation at all, so a plain \n is enough — no CR needed.

val _data = data.map(_.split("\n")).map(_.map(line => Some(s"data: $line"))).getOrElse(Array.empty[Option[String]])
val _event = eventType.map(event => s"event: $event")
val _id = id.map(id => s"id: $id")

This matters because toString is how applications render events built from their own (potentially user-supplied) values, so a caller can be made to emit fields it never intended — including data, event, id or retry.

Suggested fix

The right remedy differs per field:

  • data may legitimately span multiple lines, so it should split on all three terminators: split("\r\n|\r|\n"), each part emitted as its own data: line.
  • eventType and id cannot span lines, so splitting is not meaningful. They should have line terminators rejected or stripped.

Related

The same class of bug in the new comments field was found in review and fixed in #478 (comments now splits on \r\n|\r|\n). The three fields above are pre-existing on master and are untouched by that PR, hence this separate issue.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions