Skip to content

Local db reset recreates PostgreSQL without the read-only pgsodium_root.key bind used by supabase start #6105

Description

@coryeckles

Affected area

Database / Local development / Docker

Supabase CLI version

v2.110.0 was observed locally. The same decisive reset path is present in stable v2.111.0. The current beta, v2.112.0-beta.11, was reviewed but not executed.

Operating system

macOS 26.5.2, Darwin/arm64

Installation method

npm devDependency

Docker context

Docker Desktop desktop-linux; client Darwin/arm64, server Linux/arm64. Personal socket paths and project identifiers are redacted.

Command

supabase start
supabase db reset --local --no-seed --version <existing-migration-version>

The reset command was invoked by a guarded local-only runner. This report contains no real workspace names, project IDs, container names, ports, keys, tokens, or member data.

Actual behavior

Before reset, the PostgreSQL container created by supabase start had exactly one secret mount with this redacted shape:

Type=bind
Source=/host_mnt/private/tmp/<disposable-workspace>/supabase/.temp/start-secrets/<db-container>/secret-0
Destination=/etc/postgresql-custom/pgsodium_root.key
RW=false

Local db reset then replaced the PostgreSQL container. The successor was healthy and retained the expected database data volume, but filtering its mount inventory for the protected destination returned:

{"count":0,"rwType":"undefined"}

The local runner stopped before applying the next migration. No raw key bytes or full Docker inspect payload were read, logged, or retained.

Expected behavior

For a local Docker daemon, a reset-created PostgreSQL successor should preserve the same already-staged, authenticated host secret file as exactly one bind at /etc/postgresql-custom/pgsodium_root.key with read-only mode.

The root key should not be moved into shell argv, logs, environment, labels, or Docker Config.Entrypoint. If the exact bind cannot be preserved, reset should fail closed before destructive recreation instead of silently changing the secret-delivery representation.

Minimal conceptual reproduction

This was not rerun while preparing the report.

  1. Create a disposable, unlinked local Supabase project with PostgreSQL 15 or later and at least one migration.
  2. Run supabase start.
  3. Inspect only redacted mount metadata for the local PostgreSQL container and record the single read-only bind at the protected destination.
  4. Run supabase db reset --local --no-seed, optionally through an existing migration version.
  5. Resolve the replacement PostgreSQL container by exact local project labels.
  6. Inspect only redacted mount metadata.
  7. Observe a new container ID with the data volume but no bind at the protected destination.

Please use synthetic root-key content in any upstream fixture. Do not include a real key or an unredacted Config object in logs or snapshots.

Source trace

In v2.110.0:

As of 2026-08-06, v2.112.0-beta.10 ports database start bootstrap to TypeScript and explicitly identifies local reset recreation as a follow-up. Its docker create → docker cp → docker start secret delivery would not provide read-only bind continuity. v2.112.0-beta.11 adds an unrelated process-compose health-lifecycle fix. Current develop at 223fa146 still delegates reset recreation through the Go seam.

Impact

The reset lifecycle changes the root-key representation from an authenticated host file and read-only mount to container-managed configuration/filesystem state. That prevents provenance-sensitive local tooling from establishing start/reset continuity and can place the key in Docker-managed entrypoint configuration in v2.110.0/v2.111.0.

This report does not claim a confirmed vulnerability or assign a severity. It requests consistent, non-argv, creation-time secret handling across local start and reset.

Requested change

Please make local db reset create its PostgreSQL successor with the same authenticated read-only pgsodium_root.key bind used by local supabase start, or provide an explicit local bind-preserving mode that reset uses without a representation fallback.

Suggested regression coverage:

  • start and reset successor have the same secret source lineage, destination, bind type, and read-only mode;
  • old and new container IDs differ and both project identities are unambiguous;
  • missing, extra, wrong, or writable secret mounts fail;
  • root-key content is absent from argv, logs, snapshots, environment, labels, and Docker Config.Entrypoint; and
  • remote-Docker behavior does not silently replace the governed local bind contract.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions