Skip to content

TLS against managed Postgres: the only discoverable fix is disabling verification process-wide #889

Description

@coderdan

Reported by a Lovable agent implementing CipherStash in a Lovable-hosted project, connecting to Supabase through the pgBouncer pooler.

What happens

stash eql install aborts with:

self-signed certificate in certificate chain

The agent got past it by setting NODE_TLS_REJECT_UNAUTHORIZED=0 and sslmode=no-verify.

That is the part worth fixing. We taught an autonomous agent to disable TLS verification to get our encryption product installed, and it will now carry that habit — and quite possibly that environment variable — into whatever it builds next. NODE_TLS_REJECT_UNAUTHORIZED=0 is process-wide: it disables verification for every outbound TLS connection in that process, including the ones carrying ZeroKMS credentials.

Current state

The CLI does nothing with TLS. new pg.Client({ connectionString }) (packages/cli/src/installer/index.ts:53, :109, :137, :170) hands the URL to node-postgres and takes whatever it decides. There is no ssl: configuration, no CA bundle, and no handling of the sslmode parameter anywhere in packages/cli/src. The connect failure surfaces as Failed to connect to database: self-signed certificate in certificate chain — the symptom, with no mention of a fix.

Proposal

  1. Ship / resolve a CA bundle for the managed providers we support, so sslmode=verify-full against Supabase works out of the box.
  2. Honour sslmode and sslrootcert from the connection string properly, including verify-full with a caller-supplied root.
  3. Make the error name the fix, not the symptom. A cert-chain failure should say which host failed to verify, and offer the supported remedies in order — supply sslrootcert=<path>, or (last resort, with the consequence spelled out) sslmode=no-verify. It should never leave NODE_TLS_REJECT_UNAUTHORIZED=0 as the discoverable answer.
  4. If sslmode=no-verify is used, say so once on stderr. An unverified connection to a database holding encrypted data is a decision, not a default.

Related

#822 — the node-postgres sslmode advisory warning the CLI passes through on production URLs. Same layer, same connection-string handling; likely worth fixing together, since normalising the connection string is a candidate fix for both.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions