forked / Architecture

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

  1. connect-src is restricted to 'self', the configured sync origins, and the AI provider origins listed in ADR-024.
  2. The allowed origins are deploy-time configuration of the frontend container, so operators add their backend without editing the image: FORKED_GATEWAY_URL for an operator gateway (ADR-038) and FORKED_CSP_CONNECT_SRC for anything else, such as a CouchDB on another origin.
  3. 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.
  4. The image serves GET /forked-config.json so 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.

View source on GitHub