SPB Git

Repository Public

security.md 3.5 KB 46 lines markdown

1# Security and threat model23## Assets45xAI API key (spend), the studio (publication rights), private prompts and drafts, visitor privacy.67## Controls89| Threat | Control |10|---|---|11| Key leaks to the browser, logs or API | Key read only in `src/lib/env.ts` (server); never serialised; structured logger redacts `authorization` and anything matching `xai-…`; `scripts/secrets-scan.ts` scans client chunks and tracked files in `pnpm check` |12| Studio takeover | No default password: `scripts/bootstrap-owner.ts` generates a one-time password (scrypt hash stored), forced change at first login; TOTP second factor (enforced once enrolled); sessions are random 256-bit tokens stored hashed, `HttpOnly; Secure; SameSite=Strict`, 12 h idle / 7 d absolute; login rate limit 5/min/IP + 10/h/account |13| Privilege misuse | Roles `owner` > `editor` > `viewer`; every studio page, server action and API route calls `requireRole()` server-side; all mutations are written to `audit_log` |14| CSRF | SameSite=Strict cookie + `Origin` check on every mutating request; Server Actions are origin-checked by Next.js |15| XSS | React escaping, no `dangerouslySetInnerHTML` on user or model text, CSP (`default-src 'self'`, no remote scripts, `frame-ancestors 'none'`) |16| Runaway spend | Budget gate before every paid call, kill switch, bounded retries, regeneration cap, scheduler quota, idempotency keys (no duplicate paid generation), circuit breaker |17| SSRF | The server fetches only `api.x.ai` and provider result URLs, which are validated against an allow-list of xAI hosts (`src/providers/http.ts`). No user-supplied URL is ever fetched |18| Upload abuse | The studio accepts no file uploads in this version (all media is generated); nothing to scan. Reference uploads, if added, must validate MIME/size and run a scanner |19| Private media exposure | `/media/*` serves only assets linked to a published film; everything else needs a studio session or a signed URL (HMAC-SHA256, expiry) |20| Abuse of public write endpoints | Reactions, analytics and reports are rate-limited per hashed visitor and accept fixed-shape payloads only |21| Injection | Parameterised SQL (postgres-js tagged templates) everywhere |2223## Content safety and provenance2425- Every film carries a visible "AI-generated" disclosure, a public provenance block (models, dates, pipeline26  stages, human approval) and container metadata in the MP4 (`comment`, `description`). C2PA signing is not27  implemented (no signing certificate); the provenance JSON is served at `/api/films/:slug`.28- No impersonation: the brief validator and the Quality Critic reject real, named people; voices are provider29  presets only (no cloning).30- Factual series must pass the Research Editor: each claim needs a source, otherwise the film is labelled31  fiction/speculation or held for a human.32- Moderation happens before publication (provider moderation flag + critic safety score + human approval).33  `/report` files a takedown request; an operator can unpublish in one action (assets stop being served).3435## Visitor data3637No account, no third-party script, no advertising identifier. A visitor is a daily-rotating hash38(`sha256(secret | day | ip | user-agent)`), used only to de-duplicate views and likes; raw IPs are not stored.39Analytics events are deleted after 90 days; bookmarks live in the browser (`localStorage`).4041## Known gaps4243Passkeys (WebAuthn) are not implemented (password + TOTP instead). C2PA not implemented. No external error44tracker (structured logs + PM2 + health probe). Docker Compose file is provided but the production deployment45is PM2 on macOS.46
Files main
Menu

Theme