Skip to content

Refuse to launch psql/pgcli with an empty database target - #54

Open
puncsky wants to merge 1 commit into
render-oss:mainfrom
puncsky:fix/psql-empty-target
Open

puncsky wants to merge 1 commit into
render-oss:mainfrom
puncsky:fix/psql-empty-target

Conversation

@puncsky

@puncsky puncsky commented Oct 10, 2026 •

Copy link
Copy Markdown

Summary

When external IP discovery fails (for example api.ipify.org is unreachable), the psql view skips the IP allow-list check and builds the child command from the database's external connection string. If that string is nil or empty, render psql <db> -c "..." (and the interactive psql/pgcli path) starts the client with no connection target, so libpq falls back to its local socket or PG* environment defaults. SQL intended for the selected Render database can then run against whatever those defaults point to.

This adds getExternalConnectionString, which returns an error naming the database when the external target is nil, empty or whitespace-only, before either child command is built. The guard applies whether IP discovery succeeded or failed, so the existing "continue without the IP check" fallback still works for databases that do have an external target. getUserIP becomes a package variable so tests can fake discovery.

Motivation

Found while testing the CLI against a Render-compatible API: a private database (no external connection string) plus an IP-discovery failure launched psql with an empty target. No wrong-database query was observed, but the empty target makes one possible whenever PGHOST/PGDATABASE or a local server are present.

How to verify

  • go test ./pkg/tui/views/... — new psql_test.go covers nil, empty and whitespace targets (refused, naming the database) for both -c and interactive tools, with IP discovery both failing and succeeding, plus the valid-target path.
  • Removing the guard fails both refusal tests; removing the TrimSpace fails exactly the whitespace cases.
  • Full go test ./... passes except e2e/TestE2E, which fails identically on main without credentials (rate limited).

Release notes

`psql`/`pgcli` now refuse to start when the database has no external connection target instead of connecting to local defaults.

When external IP discovery fails, the psql view skips its IP allow-list
check and goes on to build the child command from the database's external
connection string. If that string is nil or empty, `psql -c` (and the
interactive psql/pgcli path) is started with no connection target, so libpq
falls back to its local or PG* environment defaults - SQL meant for the
selected Render database can be sent somewhere else.

Resolve the external connection string through getExternalConnectionString,
which returns an error naming the database when the value is nil, empty or
whitespace-only, before either child is built. The guard holds whether IP
discovery succeeded or failed, so the existing fallback still works for real
targets. getUserIP becomes a package variable so tests can fake discovery.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant