ADR-026: Restrictive Content Security Policy
Status: Accepted Date: 2026-10-13
Context
The PWA holds the user’s recipes and, in self-hosted mode, a sync password in the browser. A Content Security Policy that allows connect-src to any host would leave an exfiltration path open if script injection ever succeeded.
Decision
connect-srcis restricted to'self', the configured sync origins, and the AI provider origins listed in ADR-024.- The allowed origins are deploy-time configuration of the frontend container, so operators add their backend without editing the image:
FORKED_GATEWAY_URLfor an operator gateway (ADR-038) andFORKED_CSP_CONNECT_SRCfor anything else, such as a CouchDB on another origin. - The default also allows loopback (
http://localhost:*,http://127.0.0.1:*) so a local AI server works out of the box. Loopback cannot reach the internet, so the exfiltration path stays closed. - The image serves
GET /forked-config.jsonso the PWA learns at runtime which sync mode applies. There is no hard-coded default backend (Section 7.2).
Consequences
- An XSS bug can no longer send data to arbitrary hosts.
- A CouchDB or OpenAI-compatible endpoint on another origin works only after the operator allows it in the CSP. Loopback endpoints work by default.
- Invite links cannot redirect the PWA to another gateway: the announced one is always used.