Security model

High-level principles only: sessions, ownership, encryption, CSRF, headers and the boundaries between manager and project.

What it is

The security model rests on a small number of rules. Manager sessions are signed tokens in an httpOnly cookie. Every project request is checked for ownership before it is forwarded. Secrets are encrypted at rest under a master key. State-changing cookie requests carry a CSRF token. The process applies security headers, rate limits, central error redaction and process-level guards.

This page describes principles only. It is not an audit, a threat model, or a list of known issues. It explains the boundaries the product intends to maintain, so an operator can reason about them.

Why a single policy matters

A product with two entry points can easily acquire two policies. Here the path front door and the subdomain proxy call the same evaluator, so a request cannot be admitted by one route and denied by another. The same reasoning applies to the manager and the project: the manager's cookie is not a project credential, and a project key is not a manager credential.

Trust boundaries

Security boundaries and credentials Three credential types cross three boundaries. A manager session cookie is checked by the manager API. A project anon or service-role key is checked by the front-door evaluator. The service-role key is additionally required for the postgres-meta route. Vault secrets are encrypted under the vault master key. Three credentials, three checks Manager sessionJWT in httpOnly cookieplus CSRF double-submit Project API keyanon or service_rolefrom the project status Vault master keyconfiguration valueencrypts stored secrets Manager API boundaryverify session / token version / CSRF / ownership before a project route runs Front-door boundaryresolve project first, then evaluate session ownership or project key /pg/ requires service_role · Studio is not opened by an API key Secrets at restscrypt-derived key + AES-GCM for project and edge-function secrets previous master key can remain in the key ring Legend: green = request credential · violet = data-at-rest key.

Diagram: the browser holds a session cookie; the manager verifies it, checks ownership, and forwards to the project; the vault key stays inside the manager boundary, and project containers receive only the configuration they need.

Trusted boundaryVerified credentialUntrusted input

The controls

Sessions. Manager sessions are JWTs signed with JWT_SECRET, carried in an httpOnly session_token cookie, with a token version that allows revocation. The signing key must be at least 32 characters, and the well-known Supabase example value is rejected by value.

CSRF. Cookie-authenticated state changes use a double-submit token, so a cross-site form cannot act with the user's session.

Ownership. A manager session reaches only projects it owns or administers. The denial response does not disclose whether a project exists.

Encryption. Project and edge-function secrets are encrypted with scrypt and AES under VAULT_MASTER_KEY. A previous key can be retained during rotation.

Process. CLI processes are spawned without a shell. Security headers, rate limiting and central error redaction apply to the HTTP surface. The manager's own token is stripped before a proxied request leaves the process.

What is encrypted where

Data and storage layout The manager keeps projects, users and settings in a manager SQLite database in the platform data directory. Each Supabase project keeps its Postgres and storage data in Docker volumes. Project backups are SQL files under the project backup folder. Vault secrets are encrypted before storage. Three layers of state Manager database SQLite file in the platform data directory projects / users / settings port allocations / audit rows loaded in memory via sql.js Per-project data Docker volumes managed by the Supabase CLI Postgres data / storage objects project containers not copied by the builder Project files inside the registered project directory supabase/config.toml supabase/backups/*.sql written on demand Secrets and logs Project secrets and edge-function secrets are encrypted with scrypt and AES under the vault master key before storage. The master key is configuration, not database content. Its previous value can be retained during rotation. Proxy access logs and denial logs live in the manager log directory and follow the admin retention setting. The manager database is rewritten as a whole on mutation; copy it only while the manager is stopped. No product data is copied into docs/ by the site builder. manager project

Diagram: settings and vault rows live in the manager database; vault values are ciphertext; project data and backups sit outside the manager boundary.

Manager stateCiphertextProject data

Operating within the model

Keep the master key and the signing key out of source control. Use the setup script to generate them, store them where you keep the rest of the machine's secrets, and keep a copy of the master key with the database backup. Give manager accounts the smallest role that does the job. Treat the service-role key as a server credential and never ship it to a browser.

Understand the trust direction: a project is not trusted to administer the manager, and the manager does not expose a general database proxy. Each forwarded request is subject to the same ownership check regardless of the route it used.

The model also explains what the manager does not promise. It does not sandbox a project from the host, isolate projects from each other at the network level, or protect a database from a user who already has the postgres role. It concentrates on the boundary that matters for a local multi-project tool: who may reach a project through the shared entry point, and how stored secrets are kept at rest.

Failure and recovery

A missing or short signing key stops the process at boot rather than starting with a weak session scheme. A missing master key stops it in the same way. A lost master key makes vault rows unreadable; a retained previous key is the recovery path after a rotation. A revoked session is rejected on its next request. If you suspect a manager account is compromised, deactivate it and rotate the signing key, which invalidates existing sessions.

Configuration

<code>JWT_SECRET</code>
Session signing key; required, at least 32 characters.
<code>VAULT_MASTER_KEY</code>
Secret encryption key; required, at least 32 characters.
<code>VAULT_MASTER_KEY_PREVIOUS</code>
Prior key retained during rotation.
<code>ADMIN_EMAIL</code> and <code>ADMIN_PASSWORD</code>
Seed the first administrator account.
<code>PROXY_ACCEPT_LVH_ME</code>
Opt-in host suffix; off by default because it widens host routing.
This page is a description of design principles, not a security audit. For an operational review, examine the code and the test suites that pin these behaviours.