fix(datatables): hide schemas the connection's role cannot reach

This commit is contained in:
Diego Imbert
2026-08-31 04:33:22 +02:00
parent 163ff3aad6
commit 7effde8bbe
2 changed files with 13 additions and 1 deletions
@@ -2433,6 +2433,9 @@ async fn get_datatable_schema(
FROM pg_namespace
WHERE nspname NOT IN ('information_schema', 'pg_toast', 'pg_catalog')
AND nspname NOT LIKE 'pg_%'
-- Only what this connection's role can reach: a schema it cannot
-- enter would list no tables and read as an empty one.
AND has_schema_privilege(oid, 'USAGE, CREATE')
ORDER BY nspname
"#,
&[],
@@ -2524,6 +2527,9 @@ async fn get_datatable_tables(
FROM pg_namespace
WHERE nspname NOT IN ('information_schema', 'pg_toast', 'pg_catalog')
AND nspname NOT LIKE 'pg_%'
-- Only what this connection's role can reach: a schema it cannot
-- enter would list no tables and read as an empty one.
AND has_schema_privilege(oid, 'USAGE, CREATE')
ORDER BY nspname
"#,
&[],
@@ -2598,7 +2598,10 @@ WHERE table_catalog = current_database()",
)
} else {
(
"\nWHERE c.relkind = 'r' AND a.attnum > 0 AND NOT a.attisdropped\n AND ns.nspname != 'pg_catalog' AND ns.nspname != 'information_schema'".to_string(),
// pg_catalog is readable by everyone, so without the
// privilege check this lists tables of schemas the
// connection's role cannot even enter.
"\nWHERE c.relkind = 'r' AND a.attnum > 0 AND NOT a.attisdropped\n AND ns.nspname != 'pg_catalog' AND ns.nspname != 'information_schema'\n AND has_schema_privilege(ns.oid, 'USAGE, CREATE')".to_string(),
",\n ns.nspname AS schema_name,\n c.relname AS table_name".to_string(),
"\nJOIN pg_catalog.pg_class c ON a.attrelid = c.oid\nJOIN pg_catalog.pg_namespace ns ON c.relnamespace = ns.oid".to_string(),
"ns.nspname, c.relname, a.attnum".to_string(),
@@ -4468,6 +4471,9 @@ mod tests {
assert!(sql.contains("schema_name"));
assert!(sql.contains("table_name"));
assert!(sql.contains("c.relkind = 'r'"));
// Listing every table must not reach into schemas the connection's role
// cannot enter: pg_catalog itself is readable by everyone.
assert!(sql.contains("has_schema_privilege(ns.oid, 'USAGE, CREATE')"));
}
#[test]