@@ -122,3 +122,40 @@ it("properly formats multiple sse messages", () => {
122122 ] ) ;
123123 expect ( result ) . toEqual ( `data: hello world\n\nid: 1\ndata: hello world 2\n\n` ) ;
124124} ) ;
125+
126+ it ( "sanitizes newlines in event field to prevent SSE injection" , ( ) => {
127+ const result = formatEventStreamMessage ( {
128+ event : "message\nevent: admin\ndata: INJECTED" ,
129+ data : "legit" ,
130+ } ) ;
131+ expect ( result ) . toEqual (
132+ `event: messageevent: admindata: INJECTED\ndata: legit\n\n` ,
133+ ) ;
134+ expect ( result . split ( "\n" ) . filter ( ( l ) => l . startsWith ( "event:" ) ) . length ) . toBe (
135+ 1 ,
136+ ) ;
137+ } ) ;
138+
139+ it ( "sanitizes newlines in id field to prevent SSE injection" , ( ) => {
140+ const result = formatEventStreamMessage ( {
141+ id : "1\ndata: INJECTED" ,
142+ data : "legit" ,
143+ } ) ;
144+ expect ( result ) . toEqual ( `id: 1data: INJECTED\ndata: legit\n\n` ) ;
145+ } ) ;
146+
147+ it ( "splits multi-line data into separate data fields" , ( ) => {
148+ const result = formatEventStreamMessage ( {
149+ data : "line1\nline2\nline3" ,
150+ } ) ;
151+ expect ( result ) . toEqual ( `data: line1\ndata: line2\ndata: line3\n\n` ) ;
152+ } ) ;
153+
154+ it ( "prevents data field injection of new events" , ( ) => {
155+ const result = formatEventStreamMessage ( {
156+ data : "hi\n\nevent: system\ndata: INJECTED" ,
157+ } ) ;
158+ expect ( result ) . toBe (
159+ `data: hi\ndata: \ndata: event: system\ndata: data: INJECTED\n\n` ,
160+ ) ;
161+ } ) ;
0 commit comments