Skip to content

Commit 7c1fdda

Browse files
committed
add: log error when db-schemas config contain restricted schemas
We don't allow accessing schemas "pg_catalog" and "information_schema". Instead of silently failing requests on these schemas, this now adds logging an error on startup when these schemas are found in `db-schemas` config. Signed-off-by: Taimoor Zaeem <taimoorzaeem@gmail.com>
1 parent 24a27d1 commit 7c1fdda

File tree

5 files changed

+42
-2
lines changed

5 files changed

+42
-2
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. From versio
44

55
## Unreleased
66

7+
### Added
8+
9+
- Log error when `db-schemas` config contains schema `pg_catalog` or `information_schema` by @taimoorzaeem in #4359
10+
711
## [14.1] - 2025-11-05
812

913
## Fixed

docs/references/api/schemas.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ Schemas
55

66
PostgREST can expose a single or multiple schema's tables, views and functions. The :ref:`active database role <roles>` must have the usage privilege on the schemas to access them.
77

8+
.. important::
9+
10+
Postgres system schemas ``pg_catalog`` and ``information_schema`` are not allowed in :ref:`db-schemas`. This is done to prevent leaking sensitive information and hence they cannot be accessed directly. As a workaround, we suggest that you create a view in your other exposed schema, which selects from these restricted schemas.
11+
812
Single schema
913
-------------
1014

src/PostgREST/Config.hs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,7 @@ parser optPath env dbSettings roleSettings roleIsolationLvl =
274274
<*> (fromMaybe True <$> optBool "db-prepared-statements")
275275
<*> (fmap toQi <$> optWithAlias (optString "db-root-spec")
276276
(optString "root-spec"))
277-
<*> (fromList . maybe ["public"] splitOnCommas <$> optWithAlias (optString "db-schemas")
278-
(optString "db-schema"))
277+
<*> parseDbSchemas "db-schemas" "db-schema"
279278
<*> (fromMaybe True <$> optBool "db-config")
280279
<*> (fmap toQi <$> optString "db-pre-config")
281280
<*> parseTxEnd "db-tx-end" snd
@@ -329,6 +328,18 @@ parser optPath env dbSettings roleSettings roleIsolationLvl =
329328
Just asp | asp == serverPort -> fail "admin-server-port cannot be the same as server-port"
330329
| otherwise -> pure $ Just asp
331330

331+
parseDbSchemas :: C.Key -> C.Key -> C.Parser C.Config (NonEmpty Text)
332+
parseDbSchemas k al =
333+
optWithAlias (optString k) (optString al) >>= \case
334+
Nothing -> pure $ fromList ["public"]
335+
Just s
336+
| "pg_catalog" `elem` schemas -> fail (errMsg "pg_catalog")
337+
| "information_schema" `elem` schemas -> fail (errMsg "information_schema")
338+
| otherwise -> pure $ fromList schemas
339+
where
340+
schemas = splitOnCommas s
341+
errMsg x = ("db-schemas does not allow schema: '" <> x <> "'")
342+
332343
parseSocketFileMode :: C.Key -> C.Parser C.Config FileMode
333344
parseSocketFileMode k =
334345
optString k >>= \case

test/io/fixtures/fixtures.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,3 +237,7 @@ specialhostvalues:
237237
- '*6'
238238
- '!6'
239239
- '*'
240+
241+
restrictedschemas:
242+
- 'pg_catalog'
243+
- 'information_schema'

test/io/test_cli.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,23 @@ def test_jwt_secret_min_length(defaultenv):
286286
assert "The JWT secret must be at least 32 characters long." in error
287287

288288

289+
@pytest.mark.parametrize("restricted_schema", FIXTURES["restrictedschemas"])
290+
def test_restricted_db_schemas(restricted_schema, defaultenv):
291+
"Should print error when db-schemas config contain pg_catalog or information_schema"
292+
293+
# test when one schema is given in db-schemas
294+
env = {**defaultenv, "PGRST_DB_SCHEMAS": restricted_schema}
295+
296+
error = cli(["--dump-config"], env=env, expect_error=True)
297+
assert f"db-schemas does not allow schema: '{restricted_schema}'" in error
298+
299+
# test when multiple schemas are given in db-schemas
300+
env = {**defaultenv, "PGRST_DB_SCHEMAS": f"test, {restricted_schema}"}
301+
302+
error = cli(["--dump-config"], env=env, expect_error=True)
303+
assert f"db-schemas does not allow schema: '{restricted_schema}'" in error
304+
305+
289306
# TODO: Improve readability of "--ready" healthcheck tests
290307
@pytest.mark.parametrize("host", ["127.0.0.1", "::1"], ids=["IPv4", "IPv6"])
291308
def test_cli_ready_flag_success(host, defaultenv):

0 commit comments

Comments
 (0)