Skip to content

pgwire: tenant users get 'unknown table' on INSERT/SELECT against their own collections #29

@hollanf

Description

@hollanf

Summary

When a tenant-scoped user (any tenant other than tenant 1) connects via pgwire and runs INSERT or SELECT on a collection owned by their tenant, the query fails with unknown table — even though SHOW COLLECTIONS lists the collection and CREATE COLLECTION just succeeded on the same connection.

Environment

  • NodeDB v0.0.2, nodedb-0.0.2-linux-arm64 release binary
  • Running in OrbStack Ubuntu ARM64 VM, pgwire on 127.0.0.1:6432
  • Source HEAD for analysis: b024c560 (post-ci(release): add Discord notification job for new releases #28 merge)
  • Client: postgres.js via Bun, prepare: false (still hits QueryParser::parse_sql via the extended Parse/Bind/Execute flow)

Reproduction

-- as superuser (tenant 1)
CREATE TENANT acme;
-- ok — assigns tenant_id = 2

CREATE USER svc WITH PASSWORD 'x' ROLE readwrite TENANT 2;
-- ok

Reconnect as svc on pgwire :6432:

CREATE COLLECTION t2_mem TYPE DOCUMENT STRICT (
    id STRING PRIMARY KEY,
    content STRING NOT NULL
);
-- OK

SHOW COLLECTIONS;
-- lists t2_mem with owner=svc

INSERT INTO t2_mem (id, content) VALUES ('a', 'alpha');
-- ERROR: unknown table: t2_mem

SELECT * FROM t2_mem;
-- ERROR: unknown table: t2_mem

Same behaviour with tenant_admin role (e.g. the auto-created acme_admin).

Expected

A tenant 2 user should be able to INSERT/SELECT on a collection that CREATE COLLECTION just persisted without error and that SHOW COLLECTIONS lists as theirs.

Actual

unknown table on every INSERT/SELECT against a non-tenant-1 collection. Works normally as the default superuser (tenant 1).

Asymmetric cross-tenant shape (same behaviour, opposite side)

From SQL Result
tenant-2 user SELECT * FROM <tenant-1-collection> returns [] (empty) silently
tenant-1 user SELECT * FROM <tenant-2-collection> unknown table error
tenant-2 user SELECT * FROM <own tenant-2 collection> unknown table error

Storage-level data isolation itself holds — no actual row leak across tenants. But the parse-vs-execute tenant mismatch makes every tenant > 1 unable to see its own collections through the planner.

Source pointer

nodedb/src/control/server/pgwire/handler/prepared/parser.rs:37-42try_infer_types in NodeDbQueryParser.

For cross-reference, the DDL path at nodedb/src/control/server/pgwire/ddl/collection/create/handler.rs:56 reads identity.tenant_id correctly, which is why CREATE COLLECTION and SHOW COLLECTIONS work but subsequent planning does not.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions