Security Advisory - Published 2026-05-29

CVE-2026-44477: CloudNativePG PostgreSQL Privilege Escalation Self-Check

CVE-2026-44477 affects CloudNativePG clusters where the metrics exporter can leave a PostgreSQL session with more privilege than operators expect. If you run PostgreSQL on Kubernetes with CloudNativePG, check the operator version, metrics configuration, and PostgreSQL logs before treating the cluster as clean.

How this works

CloudNativePG's built-in metrics exporter needs to read PostgreSQL internals for Prometheus scraping. To do this, it opens a connection via the pod-local Unix socket as the postgres superuser, then immediately runs SET ROLE pg_monitor to "drop privileges."

Here's the problem: SET ROLE only changes current_user. The session_user remains postgres. Any SQL expression evaluated during the scrape session can run RESET ROLE to recover full superuser privileges. The READ ONLY transaction flag doesn't block this either - it only prevents writes to database state, not calls to COPY ... TO PROGRAM.

What to check instead of testing exploitation

Do not run public exploit payloads against a production database. Confirm exposure by checking the CloudNativePG version, whether custom metrics queries exist, whether the exporter is enabled, and whether logs show role resets or command execution attempts. If those indicators appear, preserve logs before changing the cluster.

Am I affected?

You're affected if:

  • You run CloudNativePG (the Kubernetes operator for PostgreSQL)
  • Version is before 1.29.1 or before 1.28.3 (on the 1.28.x branch)
  • The built-in metrics exporter is enabled (it is by default)

Check right now - 60 seconds

# Check CloudNativePG operator version:
kubectl get deployment -n cnpg-system cnpg-controller-manager -o jsonpath='{.spec.template.spec.containers[0].image}'

# Or via helm:
helm list -n cnpg-system

# Check all CNPG clusters in your environment:
kubectl get clusters.postgresql.cnpg.io --all-namespaces -o custom-columns=NS:.metadata.namespace,NAME:.metadata.name,VERSION:.status.currentPrimary

# Check if metrics exporter is running (it is by default):
kubectl get pods -n cnpg-system -o wide | grep cnpg

Check for exploitation

# Look for RESET ROLE in PostgreSQL logs:
kubectl logs -n YOUR_NS YOUR-CLUSTER-1 --since=72h | grep -i "RESET ROLE\|COPY.*TO PROGRAM"

# Check for suspicious commands executed via COPY TO PROGRAM:
kubectl exec -n YOUR_NS YOUR-CLUSTER-1 -- grep -r "TO PROGRAM" /var/lib/postgresql/data/log/ 2>/dev/null

# Check if any files were created in /tmp (common PoC target):
kubectl exec -n YOUR_NS YOUR-CLUSTER-1 -- ls -la /tmp/ | grep -v "\.s\.PGSQL"

# Check for outbound connections from the postgres pod:
kubectl exec -n YOUR_NS YOUR-CLUSTER-1 -- ss -tunp | grep -v "5432\|127.0.0.1"

What to do right now

Right now - 10 minutes

# Upgrade CloudNativePG operator:
# If using Helm:
helm repo update
helm upgrade cnpg cnpg/cloudnative-pg -n cnpg-system --version 1.29.1

# If using kubectl apply:
kubectl apply --server-side -f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.29/releases/cnpg-1.29.1.yaml

# Verify the upgrade:
kubectl get deployment -n cnpg-system cnpg-controller-manager -o jsonpath='{.spec.template.spec.containers[0].image}'

Today - review access

  • Audit custom metrics queries. If monitoring config contains custom SQL, review who can edit it and whether it accepts untrusted input.
  • Review app-level SQL injection. A separate SQL injection issue can become more serious when privileged exporter sessions are present.
  • Check PostgreSQL audit logs for RESET ROLE or COPY TO PROGRAM in the last 30 days.

This week - harden

  • Enable pg_audit. Log privilege changes and COPY commands.
  • Network policies. Restrict pod egress and limit database pod access.
  • Pod security standards. Run PostgreSQL pods with securityContext.readOnlyRootFilesystem: true where possible.
  • Least privilege service accounts. Ensure the PostgreSQL pod's K8s service account has minimal RBAC permissions.

The bigger picture

This is a classic case of "privilege demotion theater." The code looks like it drops privileges, but the mechanism (SET ROLE) is reversible by design. PostgreSQL's role system was never intended as a security boundary within a single session. The real fix (which CNPG 1.29.1 implements) is to connect as a non-superuser from the start.

If you're running databases on Kubernetes, this is a reminder to audit every component that connects to your database - operators, exporters, backup tools. They often run with more privileges than they need.

Need help?

Ping7 can review the CloudNativePG operator version, metrics configuration, PostgreSQL logs, Kubernetes RBAC, and network policies. Start from CVE Repair if you cannot confirm whether the cluster was exposed.

  • K8s/PostgreSQL audit: $149 - operator config + RBAC + network policies
  • Emergency incident response: $299 if you found signs of exploitation

Request CVE repair ->

References