Version / build tested against
origin/main @ 247131e72
Deployment mode
Origin — single node (local)
Engine(s) involved
Not engine-specific / unsure
Summary
The two client protocols disagree about what a connection's database name means. pgwire (6432) never validates it: any string authenticates and is served the bootstrapped default database, including a name that does not exist, and writes issued on that connection land in default. The native protocol (6433) resolves the name through the catalog and rejects an unknown one with 3D000 selected database does not exist. So a connection string that works over pgwire fails at the handshake the moment it is pointed at the native port, and — more quietly — a typo'd or never-created database name reads and writes real data over pgwire with nothing to indicate the requested database was ignored.
Steps to reproduce
-- Fresh data directory. One database exists, and it is named `default`.
SHOW DATABASES;
-- name | status | created_at_lsn | quota_id | collection_count | tenant_count | parent_clone
-- ---------+--------+----------------+----------+------------------+--------------+--------------
-- default | active | 0 | 0 | 0 | 0 |
-- (1 row)
-- Connect over pgwire naming a database that does not exist:
-- psql -h 127.0.0.1 -p 6432 -U nodedb -d totally_bogus_name
-- Accepted. No warning, no error.
SELECT current_schema();
-- current_schema()
-- ------------------
-- public
-- (1 row)
-- Writes on that connection are not isolated - they land in `default`:
CREATE COLLECTION bogus_db_probe; -- CREATE COLLECTION
INSERT INTO bogus_db_probe (id, v) VALUES ('x', 1); -- INSERT 1
-- Reconnect naming the real database:
-- psql -h 127.0.0.1 -p 6432 -U nodedb -d default
SELECT * FROM bogus_db_probe;
-- id | v
-- ----+---
-- x | 1
-- (1 row) <- written through a connection that named a nonexistent database
-- The same three names over the native protocol (6433), same daemon:
-- database => "default" ACCEPTED, SELECT 1 returns 1
-- database => "nodedb" REJECTED, 3D000 selected database does not exist
-- database => "totally_bogus_name" REJECTED, 3D000 selected database does not exist
--
-- Omitting the database field entirely on a native connection succeeds - it
-- falls back to the identity default, then DatabaseId::DEFAULT.
Expected behavior
One rule for both protocols. Either pgwire rejects an unknown database name with 3D000 — matching the native protocol, and matching PostgreSQL (FATAL: database "x" does not exist) — or both protocols fall back to the caller's default database when the requested name is absent.
Rejecting is the safer of the two: silently serving a database other than the one named is how a typo reaches production data.
Actual behavior
pgwire accepts every database name, validates nothing, and binds default; DDL and DML on that connection mutate default. The native protocol rejects any name absent from the catalog with 3D000. Identical credentials therefore succeed on 6432 and fail on 6433.
Severity facts
Not checked: data lost/corrupted/silently wrong; crash/hang/won't start; security or isolation boundary crossed; core functionality broken with no acceptable workaround.
Proposed severity
SEV-2 — High: major functionality broken or silently-wrong results; stored data intact
Reproducibility
Always — every attempt
Last known-good version / commit (if a regression)
Unknown — not established. Whether pgwire ever validated the name, or whether the native check is newer than the pgwire path, was not tested against an earlier build.
Environment & logs
Linux x86_64, release build, single node, fresh data directory. Ports: pgwire 6432, native 6433, auth.mode = "password".
No server log output on the pgwire path — the name is never looked up, so there is nothing to log.
Files (best-guess): nodedb/src/control/server/native/session/auth.rs holds the native check — it resolves RequestFields::Text(f).database via catalog.get_database_id_by_name, returns 3D000 on Ok(None), then re-validates the descriptor with catalog.get_database(db_id) so the default/fallback selection is checked too. The pgwire startup path has no equivalent lookup. bootstrap_default_database in nodedb/src/control/security/catalog/database.rs is what names the bootstrapped database default (DatabaseId(0)).
Before submitting
Version / build tested against
origin/main @ 247131e72Deployment mode
Origin — single node (local)
Engine(s) involved
Not engine-specific / unsure
Summary
The two client protocols disagree about what a connection's database name means. pgwire (6432) never validates it: any string authenticates and is served the bootstrapped
defaultdatabase, including a name that does not exist, and writes issued on that connection land indefault. The native protocol (6433) resolves the name through the catalog and rejects an unknown one with3D000 selected database does not exist. So a connection string that works over pgwire fails at the handshake the moment it is pointed at the native port, and — more quietly — a typo'd or never-created database name reads and writes real data over pgwire with nothing to indicate the requested database was ignored.Steps to reproduce
Expected behavior
One rule for both protocols. Either pgwire rejects an unknown database name with
3D000— matching the native protocol, and matching PostgreSQL (FATAL: database "x" does not exist) — or both protocols fall back to the caller's default database when the requested name is absent.Rejecting is the safer of the two: silently serving a database other than the one named is how a typo reaches production data.
Actual behavior
pgwire accepts every database name, validates nothing, and binds
default; DDL and DML on that connection mutatedefault. The native protocol rejects any name absent from the catalog with3D000. Identical credentials therefore succeed on 6432 and fail on 6433.Severity facts
Not checked: data lost/corrupted/silently wrong; crash/hang/won't start; security or isolation boundary crossed; core functionality broken with no acceptable workaround.
Proposed severity
SEV-2 — High: major functionality broken or silently-wrong results; stored data intact
Reproducibility
Always — every attempt
Last known-good version / commit (if a regression)
Unknown — not established. Whether pgwire ever validated the name, or whether the native check is newer than the pgwire path, was not tested against an earlier build.
Environment & logs
Linux x86_64, release build, single node, fresh data directory. Ports: pgwire 6432, native 6433,
auth.mode = "password".No server log output on the pgwire path — the name is never looked up, so there is nothing to log.
Files (best-guess):
nodedb/src/control/server/native/session/auth.rsholds the native check — it resolvesRequestFields::Text(f).databaseviacatalog.get_database_id_by_name, returns3D000onOk(None), then re-validates the descriptor withcatalog.get_database(db_id)so the default/fallback selection is checked too. The pgwire startup path has no equivalent lookup.bootstrap_default_databaseinnodedb/src/control/security/catalog/database.rsis what names the bootstrapped databasedefault(DatabaseId(0)).Before submitting
mainbuild (not a stale local branch).