Skip to content

Commit abad47f

Browse files
taimoorzaeemsteve-chavez
authored andcommitted
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 c232e97 commit abad47f

File tree

5 files changed

+40
-2
lines changed

5 files changed

+40
-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
### Fixed
812

913
- Fix misleading logs on unsupported PostgreSQL versions by @taimoorzaeem in #4519

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+
``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. If you wish to expose objects of these schemas, expose another schema that contains wrapper views or functions over ``pg_catalog`` or ``information_schema`` objects.
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: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,21 @@ 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 single schema is given in db-schemas
294+
env = {**defaultenv, "PGRST_DB_SCHEMAS": restricted_schema}
295+
error = cli(["--dump-config"], env=env, expect_error=True)
296+
assert f"db-schemas does not allow schema: '{restricted_schema}'" in error
297+
298+
# test when multiple schemas are given in db-schemas
299+
env = {**defaultenv, "PGRST_DB_SCHEMAS": f"public, {restricted_schema}"}
300+
error = cli(["--dump-config"], env=env, expect_error=True)
301+
assert f"db-schemas does not allow schema: '{restricted_schema}'" in error
302+
303+
289304
# TODO: Improve readability of "--ready" healthcheck tests
290305
@pytest.mark.parametrize("host", ["127.0.0.1", "::1"], ids=["IPv4", "IPv6"])
291306
def test_cli_ready_flag_success(host, defaultenv):

0 commit comments

Comments
 (0)