Telemetry endpoint lacks body size and field length limits #74

Closed
opened 2026-10-08 16:33:31 -04:00 by goddard · 1 comment
Collaborator

The telemetry endpoint has no body size limit and no length limits on player names or IDs (it does require the token).

Fix

  • Cap the request body size
  • Enforce length limits on player names and IDs
The telemetry endpoint has no body size limit and no length limits on player names or IDs (it does require the token). **Fix** - [x] Cap the request body size - [x] Enforce length limits on player names and IDs
goddard added the
priority
low
type/hardening
labels 2026-10-08 16:39:17 -04:00
josh was assigned by goddard 2026-10-08 17:31:49 -04:00
Author
Collaborator

Reviewed f0afd6de67. I also checked the telemetry part of 9eb3aa84c3, which references #94. The telemetry body is capped and player names and GUIDs are length-limited, so I'm closing this.

Checklist

  • Cap the request body size. api/telemetry/+server.ts now reads the body through jsonBody (request-body.ts:52-57), which allows 1 MiB. It refuses an oversized declared Content-Length up front and counts bytes while streaming, so a missing or understated length can't get past it. Oversized bodies get 413 before parsing and aren't kept in diagnostics. The token check still runs first. telemetry-limits.test.ts covers a body at exactly 1 MiB, declared, absent and understated oversize, and 401/503 still winning over the size check.
  • Enforce length limits on player names and IDs. telemetry.ts:62 now rejects a player name or guid longer than 255 characters. server and map already had the same limit (telemetry.ts:52). An over-limit value rejects the whole report without changing game evidence. Accepted values are stored untouched, including a Unicode GUID at exactly the limit. beta-test-plans.md documents both limits and the 413.

Review notes

  • The 6 telemetry and request-body test files pass locally (158 tests), and CI run 841 passed on this commit.
  • Minor and non-blocking: the 413 is thrown with error(), so SvelteKit formats the response instead of the route. Reporters that send Accept: application/json or */* get {"message": …}. Reporters that send no Accept header get SvelteKit's HTML error page (handle_fatal_error defaults to text/html). Every other telemetry error is {"ok": false, "error": …}, so a reporter that logs error shows no reason for this one case.
Reviewed f0afd6de67c576471db33d8e0b5fc94aaab15cf6. I also checked the telemetry part of 9eb3aa84c3f2e6b2a7d18880c3bc53cd218f8852, which references #94. The telemetry body is capped and player names and GUIDs are length-limited, so I'm closing this. **Checklist** - [x] **Cap the request body size.** `api/telemetry/+server.ts` now reads the body through `jsonBody` (`request-body.ts:52-57`), which allows 1 MiB. It refuses an oversized declared `Content-Length` up front and counts bytes while streaming, so a missing or understated length can't get past it. Oversized bodies get 413 before parsing and aren't kept in diagnostics. The token check still runs first. `telemetry-limits.test.ts` covers a body at exactly 1 MiB, declared, absent and understated oversize, and 401/503 still winning over the size check. - [x] **Enforce length limits on player names and IDs.** `telemetry.ts:62` now rejects a player `name` or `guid` longer than 255 characters. `server` and `map` already had the same limit (`telemetry.ts:52`). An over-limit value rejects the whole report without changing game evidence. Accepted values are stored untouched, including a Unicode GUID at exactly the limit. `beta-test-plans.md` documents both limits and the 413. **Review notes** - The 6 telemetry and request-body test files pass locally (158 tests), and CI [run 841](https://gitea.thewrightserver.net/josh/electric-cherry/actions/runs/841) passed on this commit. - Minor and non-blocking: the 413 is thrown with `error()`, so SvelteKit formats the response instead of the route. Reporters that send `Accept: application/json` or `*/*` get `{"message": …}`. Reporters that send no `Accept` header get SvelteKit's HTML error page (`handle_fatal_error` defaults to `text/html`). Every other telemetry error is `{"ok": false, "error": …}`, so a reporter that logs `error` shows no reason for this one case.
Sign in to join this conversation.