| From: | PG Bug reporting form <noreply(at)postgresql(dot)org> |
|---|---|
| To: | pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Cc: | digoal(at)126(dot)com |
| Subject: | BUG #19523: psql tab-completion shadows pg_db_role_setting |
| Date: | 2026-06-18 07:06:44 |
| Message-ID: | 19523-424457118202f570@postgresql.org |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
The following bug has been logged on the website:
Bug reference: 19523
Logged by: Zhou Digoal
Email address: digoal(at)126(dot)com
PostgreSQL version: 19beta1
Operating system: macOS
Description:
# 🐛 [BUG] psql tab-completion shadows pg_db_role_setting
## Environment
| Item | Value |
| --- | --- |
| OS | macOS 15.7.7 (build 24G720) |
| Kernel | Darwin 24.6.0 |
| Compiler | Apple clang version 17.0.0 (clang-1700.6.4.2) |
| PG version | 19beta1 (`pg_config --version`) |
| Source branch | `master` |
| Source commit | `850b9218c8e4aa7a56f4ec34a542d4a37f9e07eb` |
| `git describe` | `850b921` |
| Build flags | `--enable-debug --enable-cassert --enable-debug-symbols` |
| Configure | `$PGBIN/pg_config --configure` |
---
## Summary
The query that psql tab-completion runs to list database-scoped GUC names
(Query_for_list_of_database_vars in src/bin/psql/tab-complete.c, duplicated
in src/bin/psql/tab-complete.in.c) references the system catalog table
pg_db_role_setting without the pg_catalog. schema qualifier. A user with
CREATE privilege on any schema earlier in search_path than pg_catalog can
therefore shadow the catalog table and influence tab-completion suggestions
for ALTER DATABASE SET.
---
## Commit under test
`850b9218c8e4aa7a56f4ec34a542d4a37f9e07eb` on branch `master`. The full
source HEAD at report
time is `850b9218c8e4aa7a56f4ec34a542d4a37f9e07eb` (`git describe` →
`850b921`).
---
## Reproduction
Repro file: `/tmp/repro_pg_db_role_setting.sql`
```sql
CREATE SCHEMA attacker;
CREATE TABLE attacker.pg_db_role_setting (
setdatabase oid,
setrole oid,
setconfig text[]
);
INSERT INTO attacker.pg_db_role_setting
SELECT oid, 0, ARRAY['custom_var=value', 'session_replication_role=replica']
FROM pg_database WHERE datname = 'postgres';
SET search_path = attacker, pg_catalog;
SELECT conf FROM (
SELECT setdatabase,
pg_catalog.split_part(pg_catalog.unnest(setconfig),'=',1) conf
FROM pg_db_role_setting
) s, pg_database d
WHERE s.setdatabase = d.oid
AND conf LIKE 'c%'
AND d.datname LIKE 'p%';
RESET search_path;
DROP SCHEMA attacker CASCADE;
```
### Actual output
```
Returned one row 'custom_var' that was read from attacker.pg_db_role_setting
rather than from the system catalog (which is empty for this database).
```
### Server log (last lines)
```
CREATE SCHEMA attacker;
CREATE SCHEMA
CREATE TABLE attacker.pg_db_role_setting (
setdatabase oid,
setrole oid,
setconfig text[]
);
CREATE TABLE
INSERT INTO attacker.pg_db_role_setting
SELECT oid, 0, ARRAY['custom_var=value', 'session_replication_role=replica']
FROM pg_database WHERE datname = 'postgres';
INSERT 0 1
SET search_path = attacker, pg_catalog;
SET
SELECT conf FROM (
SELECT setdatabase,
pg_catalog.split_part(pg_catalog.unnest(setconfig),'=',1) conf
FROM pg_db_role_setting
) s, pg_database d
WHERE s.setdatabase = d.oid
AND conf LIKE 'c%'
AND d.datname LIKE 'p%';
conf
------------
custom_var
(1 row)
RESET search_path;
RESET
DROP SCHEMA attacker CASCADE;
psql:/tmp/repro_pg_db_role_setting.sql:48: NOTICE: drop cascades to table
attacker.pg_db_role_setting
DROP SCHEMA
```
### Expected output
```
Zero rows; the query should resolve pg_db_role_setting to the system catalog
table regardless of search_path.
```
---
## Why is this a bug?
Commit bf5206f (psql: Add some missing schema qualifications in describe.c)
fixed the same class of bug for describe.c but missed tab-complete.c and
tab-complete.in.c. A user who can create a table named pg_db_role_setting in
a schema that appears before pg_catalog in search_path can have psql issue
its tab-completion query against the shadow table instead of the real
catalog, returning attacker- controlled GUC names. This violates the
documented psql behavior of suggesting actual database-level GUC settings.
---
## Suggested fix
Qualify the reference in src/bin/psql/tab-complete.in.c (line 1043) and the
generated src/bin/psql/tab-complete.c (line 1064) by changing FROM
pg_db_role_setting to FROM pg_catalog.pg_db_role_setting, then regenerate
tab-complete.c on rebuild.
---
## Severity
**medium** — see Environment block.
| From | Date | Subject | |
|---|---|---|---|
| Next Message | PG Bug reporting form | 2026-06-18 07:52:50 | BUG #19524: In `contrib/btree_gist` float4/float8 GiST index operations, handling NaN values with raw C operator |
| Previous Message | Amit Langote | 2026-06-18 06:57:20 | Re: BUG #19458: OOM killer in jsonb_path_exists_opr (@?) with malformed JSONPath containing non-existent variables |