Skip to content

Add server-side input validation for user-entered comp text fields (defence-in-depth for SEC-22) #232

Description

@pokle

Follow-up to the SEC-22 stored-XSS fix in #231.

SEC-22 was fixed at the correct layer — output encoding in the frontend (shared quote-safe escapeHtml). This issue tracks the complementary, defence-in-depth input validation on the server. It is deliberately not input HTML-sanitisation: the value must still be stored raw and encoded at each output. See docs/security-output-encoding.md for the rationale (encoding on write would corrupt the CSV export, audit log, API responses, and name sorting/matching, and would not remove the render-time escape).

Scope

Add lightweight validation to the user-entered comp text fields in web/workers/competition-api/src/validators.ts:

  • registered_pilot_name, team_name, pilot_class, default_pilot_class, comp/task name, driver_contact, glider, phone, emergency_contact_name, emergency_contact_phone.

Proposed rules (Zod refinements):

  • Reject control characters (\x00-\x1f\x7f) — never legitimate in these fields.
  • Normalise Unicode (NFC) on write, so visually-identical names compare/sort/dedupe consistently.
  • Optionally reject (HTTP 400) a literal < or > in name-type fields. Real names/teams/classes never contain them, so this shrinks the attack surface without mangling O'Brien or Müller. Do not strip silently, and do not touch ", ', or & — those are legitimate and must pass through (output encoding still handles them).

Constraints

  • Length bounds already exist (z.string().min(1).max(128)) — keep them.
  • Any rejection must surface to the user as a clear validation error, not a silent edit of their data.
  • Do not HTML-encode on input, and do not remove any frontend output encoding — this is additive only.

Not in scope (separate SEC-05 close-out)

  • Consolidating the 7 per-file frontend escapeHtml copies onto web/frontend/src/escape-html.ts.
  • A lint rule forbidding innerHTML = with interpolated non-constant template literals.

Refs: PR #231, docs/security-review.md (SEC-22, SEC-05), docs/security-output-encoding.md.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions