You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The metrics exporter authenticated as the `postgres` superuser and
demoted the session with `SET ROLE pg_monitor`. A database user owning
a schema on the scrape session's `search_path` could subvert that by
running `RESET ROLE` to recover superuser privileges and
`COPY ... TO PROGRAM` to execute OS commands inside the primary pod
(`CVE-2026-44477` / `GHSA-423p-g724-fr39`).
Replace the postgres-superuser connection used by the metrics exporter
with a dedicated `cnpg_metrics_exporter` role, granted only
`pg_monitor`, mapped via `pg_ident.conf` for peer authentication on the
local Unix socket. The metrics exporter's `session_user` is therefore
never a superuser, so `RESET ROLE` and `SET SESSION AUTHORIZATION`
cannot recover superuser, and `COPY ... TO PROGRAM` (which requires
`pg_execute_server_program`, not granted by `pg_monitor`) becomes
unavailable.
As defense in depth, the monitoring transaction prepends `pg_catalog`
to the connection's `search_path` so unqualified catalog identifiers
cannot resolve to user-planted shadow objects, and the
`target_databases: '*'` expansion filters by
`pg_catalog.has_database_privilege(datname, 'CONNECT')`.
The role is created at bootstrap, alongside `streaming_replica` in
`configureInstancePermissions`, so the first scrape after a cluster
comes up has the role available. The Reconcile loop additionally
enforces drift correction on every iteration, and clears any password
set out-of-band so the role cannot be authenticated by password
regardless of operator pre-creation. The role is excluded from
`bootstrap.initdb.import` so it is created cleanly per cluster.
Databases skipped during `target_databases: '*'` expansion for missing
`CONNECT` are logged at Debug level, surfacing what would otherwise be
silent drops.
Documentation covers the role's privilege model, the `GRANT` statements
required for custom queries that read user-owned tables or target
databases where `PUBLIC CONNECT` has been revoked, manual recovery for
replica clusters upgraded before their source primary, and the upgrade
impact in `installation_upgrade.md`.
Reported-by: Mehmet Ince
Assisted-by: Claude
Signed-off-by: Gabriele Bartolini <gabriele.bartolini@enterprisedb.com>
Signed-off-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
Signed-off-by: Leonardo Cecchi <leonardo.cecchi@enterprisedb.com>
Signed-off-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com>
Co-authored-by: Marco Nenciarini <marco.nenciarini@enterprisedb.com>
Co-authored-by: Armando Ruocco <armando.ruocco@enterprisedb.com>
Co-authored-by: Leonardo Cecchi <leonardo.cecchi@enterprisedb.com>
0 commit comments