EDB CloudNativePG Cluster 1.25.9 release notes v1.30.0

Released: 29 June 2026

This release of EDB CloudNativePG Cluster is part of the LTS series for 1.25.x. EDB will continue providing LTS releases in the 1.25.x series according to our Long-Term Support policy.

EDB CloudNativePG Cluster 1.25 approaches End-of-Life.

Users are encouraged to start planning their upgrade to a newer minor version before that date.

This release of EDB CloudNativePG Cluster includes the following:

Highlights

The cluster reference is now immutable on the Database, Pooler, Publication, Subscription, and ScheduledBackup resources. Pointing one of these objects at a different cluster has no well-defined semantics and previously left the controllers in an inconsistent state; the update is now rejected at the API server via a CEL validation rule. (#10743)

Enhancements

DescriptionAddresses
Added a label selector to the Cluster scale subresource (status.selector), making a Cluster a valid targetRef for the Vertical Pod Autoscaler (VPA) and Horizontal Pod Autoscaler (HPA), which can now map a Cluster to its instance pods.

Contributed by @sebv004.

#8996
The operator now emits a `Warning` `PrimaryStatusCheckFailed` event on the `Cluster` when the primary pod is `Ready` from the kubelet perspective but the operator's `/pg/status` check fails and failover is deferred, giving users visibility into the deferral via `kubectl describe cluster`.#10509
The operator now reloads a CNPG-i plugin automatically when its pods are rolled: it watches the `EndpointSlices` backing plugin `Services` and re-enqueues every cluster using the plugin once the new pods become `Ready`, so an upgraded plugin is picked up without waiting for the next resync.#10836

Security Fixes

DescriptionAddresses
CVE-2026-55769 / GHSA-x8c2-3p4r-v9r6: search_path pinning on operator-issued connections

a database owner could plant overloaded built-in operators in the publicschema and alter the search_path so that operator introspection probes, running as the cluster superuser, resolved those overloads beforepg_catalog, a CWE-426 privilege-escalation chain (same class asCVE-2018-1058) that could lead to in-pod RCE via COPY ... FROM PROGRAM. The operator now pins search_path = pg_catalog, public, pg_temp on every pooled connection so it ships in the startup message and takes precedence over tenant-controlled defaults.

#10774, GHSA-x8c2-3p4r-v9r6
CVE-2026-55765 / GHSA-w3gf-xc94-wvmj: operator-side SCRAM-SHA-256 password encoding

the operator now SCRAM-SHA-256 encodes cleartext role passwords before issuingCREATE/ALTER ROLE ... PASSWORD, so the literal PostgreSQL parses (and that extensions such as pg_stat_statements or pgaudit may capture) is the SCRAM verifier rather than the cleartext secret. Pre-hashed (MD5 or SCRAM) values are forwarded unchanged, and the per-Secret annotationk8s.enterprisedb.io/passwordPassthrough: "enabled" opts out.

#10724, GHSA-w3gf-xc94-wvmj

Changes

DescriptionAddresses
Updated the default PostgreSQL version to 18.4.#10719
Updated the Kubernetes versions used to test the operator on public cloud providers.#10720, #10563, #11033

Bug Fixes

DescriptionAddresses
Fixed `spec.postgresql.parameters` accepting keys that are not valid PostgreSQL parameter names, which could inject arbitrary directives into `postgresql.conf`; key names are now validated by the webhook.#11029
Fixed declarative `Database`, `Publication`, and `Subscription` objects reporting a stale primary-side status forever after their cluster was demoted to a replica; the controller now re-checks the replica condition and watches the `Cluster` so a demotion is detected promptly.#10871
Fixed non-sequential pod names (for example `-1`, `-3`) caused by the instance serial counter being advanced before the corresponding `Job` and PVCs were created; the bump is now persisted only after those resources exist.#10491
Fixed a switchover deadlock when a WAL-archiver plugin was enabled on an existing cluster: with primaryUpdateMethod: switchover the primary could not be rolled out because a clean demotion needs the archiver sidecar that is still missing.

The operator now recreates the primary Pod in place so the sidecar is injected and archiving resumes. The check also covers plugins that inject the archiver as a native sidecar (an init container with restartPolicy: Always), such as the Barman Cloud plugin.

#11032, #11059
Fixed a cluster staying in `Setting up primary` indefinitely when the instance-creation Job exhausted its backoff limit; the operator now detects the terminal Job failure and marks the cluster unrecoverable, naming the failed Job and pointing to its logs.#11035
Fixed deletion of a Database, Publication, or Subscription getting stuck in Terminating on a replica cluster, where the replica gate ran before the finalizer reconciler and the finalizer was never released.

On a replica the PostgreSQL object is left to the primary cluster.

#10853
Fixed a conflicting duplicate `Database` or `Subscription` with a `delete` reclaim policy dropping the PostgreSQL object owned by the surviving CR; the drop is now gated on a recorded reconciliation.#10870
Fixed the postgres superuser being left locked out after superuser access was disabled and then re-enabled, because the cached secret version was not invalidated and the password was never re-applied.

Diagnosed by @mhartmann-jaconi.

#10834
Fixed resource leaks when concurrent Backup objects raced: backups now run in strict creation-time order, so an already-executing backup is never preempted by a newer one and its replication slot and PostgreSQL session are no longer orphaned on the primary.

Contributed by @GabriFedi97.

#10747
Fixed role reconciliation clearing the password on a PostgreSQL role when the referenced Secret could not be fetched; the role is now left untouched until the Secret becomes available, and per-action errors are aggregated for better visibility.#10053
Fixed a bootstrap failure where a metrics-exporter setup error (commonly a duplicate-key race with the controller) rolled back streaming_replicacreation and wedged replica joins.

The metrics-exporter step now runs in a separate transaction. Contributed by @BlaiseAntony.

#10749
Fixed a `ScheduledBackup` controller loop that occurred when a `Backup` was created but its status patch never landed; the controller now adopts an existing `Backup` for the next iteration instead of looping on `AlreadyExists`.#10612
Fixed bootstrap log handling so that all named log pipes (`postgres`, `postgres.csv`, and `postgres.json`) get consumers during `WithActiveInstance`, preventing regular files from being created in place of the named pipes.#10043
Fixed generation of invalid IPv6 URLs by wrapping the address in square brackets.

Contributed by @Infinoid.

#10682
Fixed an external cluster plugin still being treated as active when its configuration set `enabled: false`.#10932
Fixed a race during bootstrap recovery from an object store where the restore job could read a stale Cluster (primary not yet recorded and timeline still unset) and have its .history files rejected by the split-brain guard.

When this happened, recovery stopped at the base backup's timeline and silently dropped transactions committed on later timelines. History files are now allowed while the cluster timeline is unset. Contributed by @dennispidun.

#10818
Fixed a cache race during cluster creation when the server and client CA resolve to the same Secret (the default): a stale informer cache triggered a redundant Create that failed with AlreadyExists and could leave the cluster stuck in Unable to create required cluster objects.

The operator now reuses the already-fetched CA Secret when the names match.

#10989
Fixed the `pg_basebackup` bootstrap path overwriting or failing on a pre-existing `PGDATA` (for example after a replica Pod restart) by enforcing the same pre-flight directory check already applied by the other bootstrap methods; this also protects statically provisioned PVCs from being silently overwritten.#11006
Fixed the Cluster phase flapping between Healthy and a plugin-failure phase when a post-reconcile plugin hook returned an error; the Healthy phase is now registered as the last step of a successful reconciliation, so a loop that ends in a plugin error never reports Healthy.

Contributed by @GabriFedi97.

#10421
Fixed stale certificate data and partial reads after an external server's Secret was rotated (for example a CA bundle shrinking from two certificates to one): the file is now written atomically, so libpq always reads either the old or the new value, never a mix.

Contributed by @Anand-240.

#10975
Fixed plugin connectivity to use the plugin Service FQDN instead of its short name, avoiding failures when a cluster-level proxy is automatically injected into pods.

Contributed by @kdautrey.

#10921
Fixed excessive operator log noise from the per-request `Cluster` create/update validation webhook messages, now logged at `debug` instead of `info`.#10984
Fixed a first-primary bootstrap deadlock where a status-patch conflict after the data PVC was created but before the initialization Job was started left the orphan Pending PVC counted as an instance, blocking the bootstrap gate; the PVC-state reconciler now recreates the bootstrap Job reusing the assigned serial.#11039
Fixed external cluster names and secret selector references being joined into filesystem paths without validation, letting a .. component or path separator escape the external secrets directory when the instance manager dumps connection material; these values are now rejected at the validating webhook and re-checked at the write site.

Reported by @r0binak.

#11045
Fixed a declarative VolumeSnapshot backup being permanently marked as failed when a stale cache made the operator re-create a snapshot it had already provisioned, failing with AlreadyExists.

The operator now tolerates the collision when the existing snapshot carries this backup's label and adopts it; a collision with a foreign snapshot still surfaces as an error.

#11071
Fixed a volume snapshot backup being discarded on a transient instance-manager connection error (for example a dial timeout from a brief pod-network disruption) during the finalize step, even when its snapshots were already provisioned; such network errors are now retried instead of treated as terminal.#11069
Fixed a replica switchover losing its `status.demotionToken` when a reconcile was requeued between storing the token and cleaning up the transition metadata (for example a cleanup patch failing against a flaky webhook); the empty no-change token is no longer patched back over the stored value.#11075
Fixed kubectl cnp psql on Windows, where execution relied on a Unix-only system call and failed with "not supported by windows"; Windows now launcheskubectl exec as a child process.

Contributed by @Utkarsh-sharma47.

#10972
Fixed an unbounded memory leak in kubectl cnp logs -f on busy clusters, where a per-log-group timer was never released; timers are now reused across iterations.

Contributed by @Anand-240.

#10976