Multi-tenant data (per-owner sessions), personal data (player names + photos), public media, and a write API. Primary risks: cross-tenant data exposure, injection, media abuse, and secret leakage.
- Authorisation backstop - RLS. Every table is RLS-enabled and FORCE'd; the Worker uses a
NOBYPASSRLSrole; policies key onapp.current_owner. Even an unscoped query cannot cross owners.score_eventsis append-only. Details + the JWT upgrade in docs/RLS.md. - Input validation. Zod
.strict()on all bodies; unknown keys rejected. - Injection. Parameterised Drizzle queries; the GUC is set via
set_config(…, true)(parameterised), never string-concatenated. - Transport & headers. HTTPS only;
X-Content-Type-Options,X-Frame-Options,Referrer-Policy,Permissions-Policy, and a strict CSP. CORS allowlisted per env. - Media. Signed, short-lived URLs for private assets; strict mime + size validation on upload; immutable keys.
- PII / GDPR. Data minimisation, retention limits, and an erasure path for player photos/names. Staging never imports production data.
- Secrets. Wrangler secrets per environment; nothing sensitive in the repo; least-privilege Cloudflare API tokens in CI.
Real authentication + RBAC (then RLS via JWT auth.user_id()), WAF/bot management, secret rotation, audit logging, monitoring/alerting, automated dependency scanning, and database backups/PITR.
This is an interview / portfolio project, not a production service with a formal SLA.
| Severity | Channel |
|---|---|
| Vulnerability | GitHub Security Advisories (private) - please do not open a public issue |
| General security question | Issue with label security or contact via GitHub profile |
We aim to acknowledge reports within 72 hours and provide a fix or mitigation plan for confirmed issues affecting deployed staging/production.
In scope: cross-tenant data exposure, auth bypass, injection, unsafe media upload, secret leakage in repo or responses.
Out of scope: social engineering, physical attacks, third-party Cloudflare/Neon platform bugs (report to those vendors directly).