fix: sanitize newlines in SSE event and id fields#2580
Conversation
|
augment review |
🤖 Augment PR SummarySummary: Sanitizes SSE 🤖 Was this summary useful? React with 👍 or 👎 |
| try { | ||
| if (id != null) { | ||
| write("id: $id$NEW_LINE") | ||
| val sanitizedEvent = event.replace("\n", "").replace("\r", "") |
There was a problem hiding this comment.
javalin/src/main/java/io/javalin/http/sse/Emitter.kt:17 While CR/LF are stripped from event/id here, emit(comment: String) only splits on \n, so a comment containing \r could still terminate the line and inject additional SSE fields—worth double-checking if comment values can contain carriage returns.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| if (id != null) { | ||
| write("id: $id$NEW_LINE") | ||
| val sanitizedEvent = event.replace("\n", "").replace("\r", "") | ||
| val sanitizedId = id?.replace("\n", "")?.replace("\r", "") |
There was a problem hiding this comment.
javalin/src/main/java/io/javalin/http/sse/Emitter.kt:18 This is a security-sensitive behavior change; there are SSE tests in javalin/src/test/java/io/javalin/TestSse.kt, but none that assert event/id newlines (\n/\r) are sanitized, so a regression could go unnoticed.
Severity: low
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #2580 +/- ##
=========================================
Coverage 86.30% 86.31%
- Complexity 1542 1545 +3
=========================================
Files 157 157
Lines 4439 4442 +3
Branches 540 542 +2
=========================================
+ Hits 3831 3834 +3
Misses 374 374
Partials 234 234 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Thanks @eddieran - could you add a test or two? |
Strip \r and \n characters from event and id parameters in Emitter.emit() to prevent SSE event injection via unsanitized newlines. The data field already handles newlines correctly by splitting into separate "data:" lines, but event and id were written to the stream without any sanitization. Fixes javalin#2579
17c2af5 to
093abb3
Compare
|
Hi @tipsy — added two tests:
Also aligned the |
Bumps `javalin.version` from 7.1.0 to 7.2.0. Updates `io.javalin:javalin-bundle` from 7.1.0 to 7.2.0 Release notes *Sourced from [io.javalin:javalin-bundle's releases](https://github.com/javalin/javalin/releases).* > 7.2.0 > ----- > > What's Changed > -------------- > > * [performance] Replace Stream API with List and reduce per-request allocations by [`@tipsy`](https://github.com/tipsy) in [javalin/javalin#2567](https://redirect.github.com/javalin/javalin/pull/2567) > * feat: introduce `JavalinJackson3` as an optional `JsonMapper` implementation for Jackson 3 by [`@yvasyliev`](https://github.com/yvasyliev) in [javalin/javalin#2548](https://redirect.github.com/javalin/javalin/pull/2548) > * [workflow]: Bump codecov/codecov-action from 5.5.2 to 5.5.3 in the dependencies group by [`@dependabot`](https://github.com/dependabot)[bot] in [javalin/javalin#2569](https://redirect.github.com/javalin/javalin/pull/2569) > * Add path role inheritance by [`@AoElite`](https://github.com/AoElite) in [javalin/javalin#2553](https://redirect.github.com/javalin/javalin/pull/2553) > * [deps]: Bump the dependencies group across 1 directory with 23 updates by [`@dependabot`](https://github.com/dependabot)[bot] in [javalin/javalin#2575](https://redirect.github.com/javalin/javalin/pull/2575) > * [workflow]: Bump codecov/codecov-action from 5.5.3 to 6.0.0 in the dependencies group across 1 directory by [`@dependabot`](https://github.com/dependabot)[bot] in [javalin/javalin#2570](https://redirect.github.com/javalin/javalin/pull/2570) > * [workflow]: Bump actions/github-script from 8 to 9 in the dependencies group by [`@dependabot`](https://github.com/dependabot)[bot] in [javalin/javalin#2581](https://redirect.github.com/javalin/javalin/pull/2581) > * [cleanup] Remove JavalinTest.class by [`@vorburger`](https://github.com/vorburger) in [javalin/javalin#2584](https://redirect.github.com/javalin/javalin/pull/2584) > * [deps] Bump Jetty from 12.1.7 to 12.1.8 by [`@vorburger`](https://github.com/vorburger) in [javalin/javalin#2585](https://redirect.github.com/javalin/javalin/pull/2585) > * Add ability to emit plain data messages in SSE by [`@1cg`](https://github.com/1cg) in [javalin/javalin#2578](https://redirect.github.com/javalin/javalin/pull/2578) > * fix: sanitize newlines in SSE event and id fields by [`@eddieran`](https://github.com/eddieran) in [javalin/javalin#2580](https://redirect.github.com/javalin/javalin/pull/2580) > * [deps] Bump stable deps and sync OptionalDependency.kt by [`@tipsy`](https://github.com/tipsy) in [javalin/javalin#2588](https://redirect.github.com/javalin/javalin/pull/2588) > > New Contributors > ---------------- > > * [`@AoElite`](https://github.com/AoElite) made their first contribution in [javalin/javalin#2553](https://redirect.github.com/javalin/javalin/pull/2553) > * [`@vorburger`](https://github.com/vorburger) made their first contribution in [javalin/javalin#2584](https://redirect.github.com/javalin/javalin/pull/2584) > * [`@1cg`](https://github.com/1cg) made their first contribution in [javalin/javalin#2578](https://redirect.github.com/javalin/javalin/pull/2578) > * [`@eddieran`](https://github.com/eddieran) made their first contribution in [javalin/javalin#2580](https://redirect.github.com/javalin/javalin/pull/2580) > > **Full Changelog**: <javalin/javalin@javalin-parent-7.1.0...javalin-parent-7.2.0> Commits * [`c67b118`](javalin/javalin@c67b118) [maven-release-plugin] prepare release javalin-parent-7.2.0 * [`b89fdf7`](javalin/javalin@b89fdf7) [deps] Bump stable deps and sync OptionalDependency.kt ([#2588](https://redirect.github.com/javalin/javalin/issues/2588)) * [`a3ad657`](javalin/javalin@a3ad657) [sse] Sanitize newlines in event and id fields * [`e0f5458`](javalin/javalin@e0f5458) [sse] Add ability to emit plain data messages * [`fa51869`](javalin/javalin@fa51869) [deps] Bump Jetty from 12.1.7 to 12.1.8 ([#2585](https://redirect.github.com/javalin/javalin/issues/2585)) * [`4bc70e9`](javalin/javalin@4bc70e9) [cleanup] Remove JavalinTest.class ([#2584](https://redirect.github.com/javalin/javalin/issues/2584)) * [`1901feb`](javalin/javalin@1901feb) [workflow]: Bump actions/github-script in the dependencies group ([#2581](https://redirect.github.com/javalin/javalin/issues/2581)) * [`152f7b3`](javalin/javalin@152f7b3) [workflow]: Bump codecov/codecov-action in the dependencies group ([#2570](https://redirect.github.com/javalin/javalin/issues/2570)) * [`2c4d1ef`](javalin/javalin@2c4d1ef) [deps]: Bump the dependencies group across 1 directory with 23 updates ([#2575](https://redirect.github.com/javalin/javalin/issues/2575)) * [`64f3a75`](javalin/javalin@64f3a75) [apibuilder] Refactor role-scoping internals to Kotlin * Additional commits viewable in [compare view](javalin/javalin@7.1.0...javalin-parent-7.2.0) Updates `io.javalin.community.openapi:javalin-openapi-plugin` from 7.1.0 to 7.2.0 Release notes *Sourced from [io.javalin.community.openapi:javalin-openapi-plugin's releases](https://github.com/javalin/javalin-openapi/releases).* > 7.2.0 > ----- > > **Changes** > > * Bumped Javalin to 7.2.0 > > **Sponsors** > Thanks to everyone who supported me this month 💜 > > **Minimal requirements** > > * Java 17+ / Kotlin 2.3+ > * Javalin 7.2.0 > > 7.1.1-rc.1 > ---------- > > **Changes** > > * [javalin/javalin-openapi#275](https://redirect.github.com/javalin/javalin-openapi/issues/275) [Make ClassLoader used for loading resources configurable](javalin/javalin-openapi@de1b6b7) > > **Sponsors** > Thanks to everyone who supported me this month 💜 ... (truncated) Commits * [`123e727`](javalin/javalin-openapi@123e727) [GH-279](https://redirect.github.com/javalin/javalin-openapi/issues/279) Adjust to Javalin's breaking changed in InternalRouter * [`3ea0e98`](javalin/javalin-openapi@3ea0e98) [GH-279](https://redirect.github.com/javalin/javalin-openapi/issues/279) Release 7.2.0 (Resolves [#279](https://redirect.github.com/javalin/javalin-openapi/issues/279)) * [`0471f8a`](javalin/javalin-openapi@0471f8a) [GH-277](https://redirect.github.com/javalin/javalin-openapi/issues/277) Release 7.1.1-rc.2 * [`3831f78`](javalin/javalin-openapi@3831f78) [GH-277](https://redirect.github.com/javalin/javalin-openapi/issues/277) Cover handling of complex types in query parameters (Resolves [#277](https://redirect.github.com/javalin/javalin-openapi/issues/277)) * See full diff in [compare view](javalin/javalin-openapi@7.1.0...7.2.0) Updates `io.javalin.community.openapi:javalin-swagger-plugin` from 7.1.0 to 7.2.0 Release notes *Sourced from [io.javalin.community.openapi:javalin-swagger-plugin's releases](https://github.com/javalin/javalin-openapi/releases).* > 7.2.0 > ----- > > **Changes** > > * Bumped Javalin to 7.2.0 > > **Sponsors** > Thanks to everyone who supported me this month 💜 > > **Minimal requirements** > > * Java 17+ / Kotlin 2.3+ > * Javalin 7.2.0 > > 7.1.1-rc.1 > ---------- > > **Changes** > > * [javalin/javalin-openapi#275](https://redirect.github.com/javalin/javalin-openapi/issues/275) [Make ClassLoader used for loading resources configurable](javalin/javalin-openapi@de1b6b7) > > **Sponsors** > Thanks to everyone who supported me this month 💜 ... (truncated) Commits * [`123e727`](javalin/javalin-openapi@123e727) [GH-279](https://redirect.github.com/javalin/javalin-openapi/issues/279) Adjust to Javalin's breaking changed in InternalRouter * [`3ea0e98`](javalin/javalin-openapi@3ea0e98) [GH-279](https://redirect.github.com/javalin/javalin-openapi/issues/279) Release 7.2.0 (Resolves [#279](https://redirect.github.com/javalin/javalin-openapi/issues/279)) * [`0471f8a`](javalin/javalin-openapi@0471f8a) [GH-277](https://redirect.github.com/javalin/javalin-openapi/issues/277) Release 7.1.1-rc.2 * [`3831f78`](javalin/javalin-openapi@3831f78) [GH-277](https://redirect.github.com/javalin/javalin-openapi/issues/277) Cover handling of complex types in query parameters (Resolves [#277](https://redirect.github.com/javalin/javalin-openapi/issues/277)) * See full diff in [compare view](javalin/javalin-openapi@7.1.0...7.2.0) Updates `io.javalin:javalin-micrometer` from 7.1.0 to 7.2.0 Release notes *Sourced from [io.javalin:javalin-micrometer's releases](https://github.com/javalin/javalin/releases).* > 7.2.0 > ----- > > What's Changed > -------------- > > * [performance] Replace Stream API with List and reduce per-request allocations by [`@tipsy`](https://github.com/tipsy) in [javalin/javalin#2567](https://redirect.github.com/javalin/javalin/pull/2567) > * feat: introduce `JavalinJackson3` as an optional `JsonMapper` implementation for Jackson 3 by [`@yvasyliev`](https://github.com/yvasyliev) in [javalin/javalin#2548](https://redirect.github.com/javalin/javalin/pull/2548) > * [workflow]: Bump codecov/codecov-action from 5.5.2 to 5.5.3 in the dependencies group by [`@dependabot`](https://github.com/dependabot)[bot] in [javalin/javalin#2569](https://redirect.github.com/javalin/javalin/pull/2569) > * Add path role inheritance by [`@AoElite`](https://github.com/AoElite) in [javalin/javalin#2553](https://redirect.github.com/javalin/javalin/pull/2553) > * [deps]: Bump the dependencies group across 1 directory with 23 updates by [`@dependabot`](https://github.com/dependabot)[bot] in [javalin/javalin#2575](https://redirect.github.com/javalin/javalin/pull/2575) > * [workflow]: Bump codecov/codecov-action from 5.5.3 to 6.0.0 in the dependencies group across 1 directory by [`@dependabot`](https://github.com/dependabot)[bot] in [javalin/javalin#2570](https://redirect.github.com/javalin/javalin/pull/2570) > * [workflow]: Bump actions/github-script from 8 to 9 in the dependencies group by [`@dependabot`](https://github.com/dependabot)[bot] in [javalin/javalin#2581](https://redirect.github.com/javalin/javalin/pull/2581) > * [cleanup] Remove JavalinTest.class by [`@vorburger`](https://github.com/vorburger) in [javalin/javalin#2584](https://redirect.github.com/javalin/javalin/pull/2584) > * [deps] Bump Jetty from 12.1.7 to 12.1.8 by [`@vorburger`](https://github.com/vorburger) in [javalin/javalin#2585](https://redirect.github.com/javalin/javalin/pull/2585) > * Add ability to emit plain data messages in SSE by [`@1cg`](https://github.com/1cg) in [javalin/javalin#2578](https://redirect.github.com/javalin/javalin/pull/2578) > * fix: sanitize newlines in SSE event and id fields by [`@eddieran`](https://github.com/eddieran) in [javalin/javalin#2580](https://redirect.github.com/javalin/javalin/pull/2580) > * [deps] Bump stable deps and sync OptionalDependency.kt by [`@tipsy`](https://github.com/tipsy) in [javalin/javalin#2588](https://redirect.github.com/javalin/javalin/pull/2588) > > New Contributors > ---------------- > > * [`@AoElite`](https://github.com/AoElite) made their first contribution in [javalin/javalin#2553](https://redirect.github.com/javalin/javalin/pull/2553) > * [`@vorburger`](https://github.com/vorburger) made their first contribution in [javalin/javalin#2584](https://redirect.github.com/javalin/javalin/pull/2584) > * [`@1cg`](https://github.com/1cg) made their first contribution in [javalin/javalin#2578](https://redirect.github.com/javalin/javalin/pull/2578) > * [`@eddieran`](https://github.com/eddieran) made their first contribution in [javalin/javalin#2580](https://redirect.github.com/javalin/javalin/pull/2580) > > **Full Changelog**: <javalin/javalin@javalin-parent-7.1.0...javalin-parent-7.2.0> Commits * [`c67b118`](javalin/javalin@c67b118) [maven-release-plugin] prepare release javalin-parent-7.2.0 * [`b89fdf7`](javalin/javalin@b89fdf7) [deps] Bump stable deps and sync OptionalDependency.kt ([#2588](https://redirect.github.com/javalin/javalin/issues/2588)) * [`a3ad657`](javalin/javalin@a3ad657) [sse] Sanitize newlines in event and id fields * [`e0f5458`](javalin/javalin@e0f5458) [sse] Add ability to emit plain data messages * [`fa51869`](javalin/javalin@fa51869) [deps] Bump Jetty from 12.1.7 to 12.1.8 ([#2585](https://redirect.github.com/javalin/javalin/issues/2585)) * [`4bc70e9`](javalin/javalin@4bc70e9) [cleanup] Remove JavalinTest.class ([#2584](https://redirect.github.com/javalin/javalin/issues/2584)) * [`1901feb`](javalin/javalin@1901feb) [workflow]: Bump actions/github-script in the dependencies group ([#2581](https://redirect.github.com/javalin/javalin/issues/2581)) * [`152f7b3`](javalin/javalin@152f7b3) [workflow]: Bump codecov/codecov-action in the dependencies group ([#2570](https://redirect.github.com/javalin/javalin/issues/2570)) * [`2c4d1ef`](javalin/javalin@2c4d1ef) [deps]: Bump the dependencies group across 1 directory with 23 updates ([#2575](https://redirect.github.com/javalin/javalin/issues/2575)) * [`64f3a75`](javalin/javalin@64f3a75) [apibuilder] Refactor role-scoping internals to Kotlin * Additional commits viewable in [compare view](javalin/javalin@7.1.0...javalin-parent-7.2.0) Updates `io.javalin:javalin-testtools` from 7.1.0 to 7.2.0 Release notes *Sourced from [io.javalin:javalin-testtools's releases](https://github.com/javalin/javalin/releases).* > 7.2.0 > ----- > > What's Changed > -------------- > > * [performance] Replace Stream API with List and reduce per-request allocations by [`@tipsy`](https://github.com/tipsy) in [javalin/javalin#2567](https://redirect.github.com/javalin/javalin/pull/2567) > * feat: introduce `JavalinJackson3` as an optional `JsonMapper` implementation for Jackson 3 by [`@yvasyliev`](https://github.com/yvasyliev) in [javalin/javalin#2548](https://redirect.github.com/javalin/javalin/pull/2548) > * [workflow]: Bump codecov/codecov-action from 5.5.2 to 5.5.3 in the dependencies group by [`@dependabot`](https://github.com/dependabot)[bot] in [javalin/javalin#2569](https://redirect.github.com/javalin/javalin/pull/2569) > * Add path role inheritance by [`@AoElite`](https://github.com/AoElite) in [javalin/javalin#2553](https://redirect.github.com/javalin/javalin/pull/2553) > * [deps]: Bump the dependencies group across 1 directory with 23 updates by [`@dependabot`](https://github.com/dependabot)[bot] in [javalin/javalin#2575](https://redirect.github.com/javalin/javalin/pull/2575) > * [workflow]: Bump codecov/codecov-action from 5.5.3 to 6.0.0 in the dependencies group across 1 directory by [`@dependabot`](https://github.com/dependabot)[bot] in [javalin/javalin#2570](https://redirect.github.com/javalin/javalin/pull/2570) > * [workflow]: Bump actions/github-script from 8 to 9 in the dependencies group by [`@dependabot`](https://github.com/dependabot)[bot] in [javalin/javalin#2581](https://redirect.github.com/javalin/javalin/pull/2581) > * [cleanup] Remove JavalinTest.class by [`@vorburger`](https://github.com/vorburger) in [javalin/javalin#2584](https://redirect.github.com/javalin/javalin/pull/2584) > * [deps] Bump Jetty from 12.1.7 to 12.1.8 by [`@vorburger`](https://github.com/vorburger) in [javalin/javalin#2585](https://redirect.github.com/javalin/javalin/pull/2585) > * Add ability to emit plain data messages in SSE by [`@1cg`](https://github.com/1cg) in [javalin/javalin#2578](https://redirect.github.com/javalin/javalin/pull/2578) > * fix: sanitize newlines in SSE event and id fields by [`@eddieran`](https://github.com/eddieran) in [javalin/javalin#2580](https://redirect.github.com/javalin/javalin/pull/2580) > * [deps] Bump stable deps and sync OptionalDependency.kt by [`@tipsy`](https://github.com/tipsy) in [javalin/javalin#2588](https://redirect.github.com/javalin/javalin/pull/2588) > > New Contributors > ---------------- > > * [`@AoElite`](https://github.com/AoElite) made their first contribution in [javalin/javalin#2553](https://redirect.github.com/javalin/javalin/pull/2553) > * [`@vorburger`](https://github.com/vorburger) made their first contribution in [javalin/javalin#2584](https://redirect.github.com/javalin/javalin/pull/2584) > * [`@1cg`](https://github.com/1cg) made their first contribution in [javalin/javalin#2578](https://redirect.github.com/javalin/javalin/pull/2578) > * [`@eddieran`](https://github.com/eddieran) made their first contribution in [javalin/javalin#2580](https://redirect.github.com/javalin/javalin/pull/2580) > > **Full Changelog**: <javalin/javalin@javalin-parent-7.1.0...javalin-parent-7.2.0> Commits * [`c67b118`](javalin/javalin@c67b118) [maven-release-plugin] prepare release javalin-parent-7.2.0 * [`b89fdf7`](javalin/javalin@b89fdf7) [deps] Bump stable deps and sync OptionalDependency.kt ([#2588](https://redirect.github.com/javalin/javalin/issues/2588)) * [`a3ad657`](javalin/javalin@a3ad657) [sse] Sanitize newlines in event and id fields * [`e0f5458`](javalin/javalin@e0f5458) [sse] Add ability to emit plain data messages * [`fa51869`](javalin/javalin@fa51869) [deps] Bump Jetty from 12.1.7 to 12.1.8 ([#2585](https://redirect.github.com/javalin/javalin/issues/2585)) * [`4bc70e9`](javalin/javalin@4bc70e9) [cleanup] Remove JavalinTest.class ([#2584](https://redirect.github.com/javalin/javalin/issues/2584)) * [`1901feb`](javalin/javalin@1901feb) [workflow]: Bump actions/github-script in the dependencies group ([#2581](https://redirect.github.com/javalin/javalin/issues/2581)) * [`152f7b3`](javalin/javalin@152f7b3) [workflow]: Bump codecov/codecov-action in the dependencies group ([#2570](https://redirect.github.com/javalin/javalin/issues/2570)) * [`2c4d1ef`](javalin/javalin@2c4d1ef) [deps]: Bump the dependencies group across 1 directory with 23 updates ([#2575](https://redirect.github.com/javalin/javalin/issues/2575)) * [`64f3a75`](javalin/javalin@64f3a75) [apibuilder] Refactor role-scoping internals to Kotlin * Additional commits viewable in [compare view](javalin/javalin@7.1.0...javalin-parent-7.2.0)
Summary
Fixes #2579
The
Emitter.emit(event, data, id)method writes theeventandidparameters directly into the SSE stream without sanitizing newline characters. This allows an attacker who controls these fields to inject arbitrary SSE fields (e.g., injecting a fakedata:line by embedding\ndata: maliciousinside an event name or id).The
dataparameter already handles newlines correctly by splitting into separatedata:lines, andemit(comment)similarly splits on newlines. However,eventandidwere passed through unsanitized.Fix
Strip
\rand\nfromeventandidbefore writing them to the output stream. This is consistent with the SSE spec, which defines event and id fields as single-line values.Test plan
\nor\rhave those characters stripped, preventing field injection