Security
CloudNativePG is designed to be secure by default, following the “Least Privilege” principle across all layers of the stack. This document outlines our security governance, supply chain integrity, and the technical controls analyzed at three distinct layers: Code, Container, and Cluster.
Warning
The information contained in this page must not exonerate you from performing regular InfoSec duties on your Kubernetes cluster. Please familiarize yourself with the
Overview of Cloud Native Security
page from the Kubernetes documentation.
Note
Please refer to
The 4C’s Security Model in Kubernetes
blog article to get a better understanding and context of the approach EDB has taken with security in CloudNativePG.
Governance and Trust
Vulnerability Reporting
important Please do not report security vulnerabilities through public GitHub issues.
CloudNativePG follows a coordinated disclosure model. For instructions on how to report a vulnerability privately, please refer to our Security Policy on GitHub .
Release Integrity and Supply Chain
CloudNativePG follows the OpenSSF Software Producer Security (OSPS) Baseline . All official release assets, including Kubernetes manifests and container images, are cryptographically signed and verifiable.
For quick-start instructions on verifying these assets during installation, see the Installation Guide . Detailed information on our Image Signatures and Attestations
can be found below.
Code
CloudNativePG’s source code undergoes systematic static analysis, including checks for security vulnerabilities, using the popular open-source linter for Go, GolangCI-Lint , directly integrated into the CI/CD pipeline. GolangCI-Lint can run multiple linters on the same source code.
The following tools are used to identify security issues:
** Golang Security Checker (
gosec):** A linter that scans the abstract syntax tree of the source code against a set of rules designed to detect known vulnerabilities, threats, and weaknesses, such as hard-coded credentials, integer overflows, and SQL injections. GolangCI-Lint runsgosecas part of its suite.** govulncheck :** This tool runs in the CI/CD pipeline and reports known vulnerabilities affecting Go code or the compiler. If the operator is built with a version of the Go compiler containing a known vulnerability,
govulncheckwill detect it.** CodeQL :** Provided by GitHub, this tool scans for security issues and blocks any pull request with detected vulnerabilities. CodeQL is configured to review only Go code, excluding other languages in the repository such as Python or Bash.
** Snyk :** Conducts nightly code scans in a scheduled job and generates weekly reports highlighting any new findings related to code security and licensing issues.
The CloudNativePG repository has the “Private vulnerability reporting” option enabled in the Security section . This feature allows users to safely report security issues that require careful handling before being publicly disclosed. If you discover any security bug, please use this medium to report it.
Note
A failure in the static code analysis phase of the CI/CD pipeline will block the entire delivery process of CloudNativePG. Every commit must pass all the linters defined by GolangCI-Lint.
Container
Every container image in CloudNativePG is automatically built via CI/CD pipelines after every commit. These images include not only the operator’s image but also the operands’ images, specifically for every supported PostgreSQL version.
Note
All operand images are automatically and regularly rebuilt by our pipelines to incorporate the latest security updates at both the base image and package levels. This ensures that container images distributed to the community receive patch-level updates regularly.
During the CI/CD process, images are scanned using the following tools:
** Dockle :** Ensures best practices in the container build process.
** Snyk :** Detects security issues within the container and reports findings via the GitHub interface.
Image Signatures
The operator and operandimages are cryptographically signed using cosign , a signature tool from sigstore . This process is automated via GitHub Actions and leverages short-lived tokens issued through OpenID Connect .
The token issuer is https://token.actions.githubusercontent.com ,
and the signing identity corresponds to a GitHub workflow executed under
the cloudnative-pg repository. This workflow uses the cosign-installer action
to streamline the signing process.
To verify the authenticity of an operator image, use the following
cosign command with the image digest:
cosign verify ghcr.io/cloudnative-pg/cloudnative-pg@sha256:<DIGEST> \
--certificate-identity-regexp="^https://github.com/cloudnative-pg/cloudnative-pg/.github/workflows/release-publish.yml@refs/tags/v" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com"
Attestations
Container images include the following attestations for transparency and traceability:
** Software Bill of Materials (SBOM) :** A comprehensive list of software artifacts included in the image or used during its build process, formatted using the in-toto SPDX predicate standard .
Provenance: Metadata detailing the build process, generated via the SLSA GitHub Generator Github action . This provides SLSA Level 3 assurance
that the artifact was built on a trusted, isolated GitHub Actions runner directly from the project’s source.
You can retrieve the SBOM for a specific image and platform using the following command:
docker buildx imagetools inspect <IMAGE> \
--format {{ json (index .SBOM "<PLATFORM>").SPDX }}
This command outputs the SBOM in JSON format, providing a detailed view of the software components and build dependencies.
For the build-level provenance, use:
docker buildx imagetools inspect <IMAGE> \
--format {{ json (index .Provenance "<PLATFORM>").SLSA }}
Verifying SLSA provenance
You can verify SLSA Level 3 provenance using slsa-verifier .
To verify a container image, pass its digest reference:
slsa-verifier verify-image \
ghcr.io/cloudnative-pg/cloudnative-pg@sha256:<DIGEST> \
--source-uri github.com/cloudnative-pg/cloudnative-pg
Guidelines and Frameworks for Container Security
The following guidelines and frameworks have been considered for ensuring container-level security:
** Container Image Creation and Deployment Guide :** Developed by the Defense Information Systems Agency (DISA) of the United States Department of Defense (DoD).
**
- CIS Benchmark for Docker :** Developed by the Center for Internet
Security (CIS).
Note
For more information on the approach that EDB has taken regarding security at the container level in CloudNativePG, please refer to the blog article
Cluster
Security at the cluster level takes into account all Kubernetes components that form both the control plane and the nodes, as well as the applications that run in the cluster (PostgreSQL included). We start by defining the trust model and the security boundaries that frame the rest of this section.
Trust Model and Security Boundaries
CloudNativePG follows a clear separation of responsibilities between the operator and the Kubernetes platform for enforcing security policies. The subsections below describe who is trusted to influence the PostgreSQL Pods, where the enforcement boundary actually lies, how the operator confines the resources it manages, and how access to all of this is governed by RBAC.
Trusted Cluster Resource Writers
Any user with create or update permissions on the Cluster custom
resource is trusted to define the full specification of the PostgreSQL
Pods that the operator manages. This includes security-sensitive fields
such as spec.securityContext , spec.podSecurityContext , and
spec.serviceAccountName . The operator applies these settings as
instructed. When a Cluster writer does not override them, the operator
applies a hardened default Pod and container security context (see
Pod and Container Security Contexts ).
This is consistent with how all Kubernetes operators work: the operator acts as a privileged agent that translates high-level intent into low-level Kubernetes resources. Granting someone write access to a Cluster resource is equivalent to granting them control over the resulting Pods, Services, PVCs, and other managed resources.
The same principle applies to CNPG-I plugins . A plugin hooks into the Pod lifecycle and can modify any field of the Pod specification before the Pod is created. Installing a plugin is therefore an explicit trust decision made by the cluster administrator, on par with granting write access to a Cluster resource.
The same authority extends into the database itself: because the operator reconciles PostgreSQL as the superuser, a Cluster writer gains superuser-level influence over the resulting cluster through documented, intended fields, including:
the bootstrap SQL hooks
postInitSQL,postInitApplicationSQL, andpostInitTemplateSQL, executed as thepostgressuperuser at initialization (see Executing Queries After Initialization );
(spec.managed.roles ), which may set superuser: true or grant
membership of existing roles, and can use PostgreSQL features such as
COPY ... FROM PROGRAM to run commands inside the operand Pod;
custom PostgreSQL configuration, including Configuring `pg_hba.conf <Configuring pg_hba.conf>` rules (for example
trustauthentication) and parameters that shape the cluster’s security posture and durability, such aspassword_encryption,fsync, and memory-related settings.
This is the intended trust model, not a privilege escalation.
Code running in the operand Pod also runs under its mounted
ServiceAccount , which can read the Secrets associated with its own
cluster (see Calls to the API server made by the instance manager
and Secrets ). A Cluster writer can therefore read those Secrets, confined by Namespace Isolation to the Cluster’s own namespace.
Note
These trust boundaries are also covered in the project's self security assessment .
Kubernetes Admission Control
The operator creates Pods through the standard Kubernetes API, meaning every Pod goes through the full admission control chain configured on the cluster. This includes Pod Security Admission
(PSA), the built-in Kubernetes mechanism that enforces Pod Security Standards
at the namespace level, as well as any third-party policy engine in use.
If a namespace enforces the PSA restricted or baseline profile,
the Kubernetes API server rejects any Pod that violates the policy,
including Pods created by the operator.
Because the trusted Cluster writers described above can set any Pod field, this admission control chain (not the operator) is the boundary that enforces Pod security policies in your environment.
Namespace Isolation
The operator confines all managed resources to the namespace of their parent Cluster. Instance Pods are always created in the same namespace as their Cluster, set explicitly and deterministically rather than inferred from any other relationship. Because Kubernetes owner references are confined to a single namespace, the operator also cannot establish ownership of resources in any other namespace.
RBAC on Custom Resources
Access to CloudNativePG custom resources is governed by standard
Kubernetes RBAC. Since write access to a Cluster resource implies
control over the resulting Pods, annotations like cnpg.io/podPatch
(which applies a user-supplied patch to the managed Pods),
cnpg.io/validation , and cnpg.io/reconciliationLoop are subject
to the same RBAC rules as the Cluster resource itself.
In particular, setting cnpg.io/validation to disabled bypasses
the operator’s own validating admission webhook for that Cluster,
including the syntactic and applicability checks performed on
cnpg.io/podPatch . CloudNativePG’s webhook validation is therefore
advisory: it can be turned off by the same actor who can write the
Cluster, so it is not a security boundary. Kubernetes admission control
still applies to the resulting Pods regardless of this annotation.
The same reasoning applies to the DatabaseRole resource: its
specification allows superuser: true and membership of any existing
role through inRoles , including the postgres role itself. Write
access to DatabaseRole objects in a namespace is therefore
equivalent to superuser access on the PostgreSQL clusters in that
namespace, and deserves the same care as write access to the Cluster
resource.
Treat write access to these resources as a high-privilege grant: for multi-tenant deployments, isolate tenants in separate namespaces and scope it per namespace with Kubernetes RBAC, relying on Namespace Isolation to bound the impact.
The RBAC discussed here governs access to CloudNativePG’s own custom resources. The next section covers the complementary side: the RBAC that the operator itself relies on to manage Kubernetes resources on your behalf.
Role Based Access Control (RBAC)
This section covers the operator’s own RBAC (the service account and roles it uses to manage Kubernetes resources on your behalf), as opposed to the user access to custom resources discussed in RBAC on Custom Resources above.
The operator interacts with the Kubernetes API server using a dedicated
service account named cnpg-manager . This service account is
typically installed in the operator namespace, commonly cnpg-system
. However, the namespace may vary based on the deployment method (see
the subsection below).
In the same namespace, there is a binding between the cnpg-manager
service account and a role. The specific name and type of this role
(either Role or ClusterRole ) also depend on the deployment
method. This role defines the necessary permissions required by the
operator to function correctly. To learn more about these roles, you can
use the kubectl describe clusterrole or kubectl describe role
commands, depending on the deployment method.
Note
The above permissions are exclusively reserved for the operator's service account to interact with the Kubernetes API server. They are not directly accessible by the users of the operator that interact only with Cluster , Pooler , Backup , ScheduledBackup , Database , Publication , Subscription , ImageCatalog and ClusterImageCatalog resources.
Below we provide some examples and, most importantly, the reasons why CloudNativePG requires full or partial management of standard Kubernetes namespaced or non-namespaced resources.
configmaps
The operator needs to create and manage default config maps for the Prometheus exporter monitoring metrics.
deployments
The operator needs to manage a PgBouncer connection pooler using a
standard Kubernetes Deployment resource.
jobs
The operator needs to handle jobs to manage different Cluster ’s
phases.
persistentvolumeclaims
The volume where the PGDATA resides is the central element of a
PostgreSQL Cluster resource; the operator needs to interact with the
selected storage class to dynamically provision the requested volumes,
based on the defined scheduling policies.
pods
The operator needs to manage Cluster ’s instances.
secrets
Unless you provide certificates and passwords to your Cluster
objects, the operator adopts the “convention over configuration”
paradigm by self-provisioning random generated passwords and TLS
certificates, and by storing them in secrets.
serviceaccounts
The operator needs to create a service account that enables the instance
manager (which is the PID 1 process of the container that controls the
PostgreSQL server) to safely communicate with the Kubernetes API server
to coordinate actions and continuously provide a reliable status of the
Cluster .
services
The operator needs to control network access to the PostgreSQL cluster (or the connection pooler) from applications, and properly manage failover/switchover operations in an automated way (by assigning, for example, the correct end-point of a service to the proper primary PostgreSQL instance).
validatingwebhookconfigurations and
mutatingwebhookconfigurations
The operator injects its self-signed webhook CA into both webhook configurations, which are needed to validate and mutate all the resources it manages. For more details, please see the Kubernetes documentation .
volumesnapshots
The operator needs to generate VolumeSnapshots objects in order to
take backups of a PostgreSQL server. VolumeSnapshots are read too in
order to validate them before starting the restore process.
nodes
The operator needs to get the labels for Affinity and AntiAffinity so it can decide in which nodes a pod can be scheduled. This is useful, for example, to prevent the replicas from being scheduled in the same node - especially important if nodes are in different availability zones. This permission is also used to determine whether a node is scheduled, preventing the creation of pods on unscheduled nodes, or triggering a switchover if the primary lives in an unscheduled node.
Deployments and ClusterRole Resources
As mentioned above, each deployment method may have variations in the namespace location of the service account, as well as the names and types of role bindings and respective roles.
Via Kubernetes Manifest
When installing CloudNativePG using the Kubernetes manifest, permissions
are set to ClusterRoleBinding by default. You can inspect the
permissions required by the operator by running:
kubectl describe clusterrole cnpg-manager
Via OLM
From a security perspective, the Operator Lifecycle Manager (OLM) provides a more flexible deployment method. It allows you to configure the operator to watch either all namespaces or specific namespaces, enabling more granular permission management.
Note
OLM allows you to deploy the operator in its own namespace and configure it to watch specific namespaces used for CloudNativePG clusters. This setup helps to contain permissions and restrict access more effectively.
Why Are ClusterRole Permissions Needed?
The operator currently requires ClusterRole permissions to read
nodes and ClusterImageCatalog objects. All other permissions can
be namespace-scoped (i.e., Role ) or cluster-wide (i.e.,
ClusterRole ).
Even with these permissions, if someone gains access to the
ServiceAccount , they will only have get , list , and
watch permissions, which are limited to viewing resources. However,
if an unauthorized user gains access to the ServiceAccount , it
indicates a more significant security issue.
Therefore, it’s crucial to prevent users from accessing the operator’s
ServiceAccount and any other ServiceAccount with elevated
permissions.
Calls to the API server made by the instance manager
The instance manager, which is the entry point of the operand container,
needs to make some calls to the Kubernetes API server to ensure that the
status of some resources is correctly updated and to access the config
maps and secrets that are associated with that Postgres cluster. Such
calls are performed through a dedicated ServiceAccount created by
the operator that shares the same PostgreSQL Cluster resource name.
Note
The operand can only access a specific and limited subset of resources through the API server. A service account is the recommended way to access the API server from within a Pod .
Pod and Container Security Contexts
defines privilege and access control settings for a pod or container.
CloudNativePG does not require privileged mode for container
execution. The PostgreSQL containers run as the postgres system
user. No component whatsoever requires running as root .
Likewise, Volume access does not require privileged mode nor root
privileges. Proper permissions must be assigned by the Kubernetes
platform and/or administrators. The PostgreSQL containers run with a
read-only root filesystem (i.e. no writable layer).
The operator manages the setting of security contexts for all pods and containers of a PostgreSQL cluster. The Seccomp Profile
to be used for the PostgreSQL containers can be configured with the
spec.seccompProfile section of the Cluster resource. If this
section is left blank, the containers will use a seccompProfile Type
of RuntimeDefault , that is, the container runtime default.
The security context of PostgreSQL containers using the default
seccompProfile will look like this:
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
Customizing Security Contexts
CloudNativePG provides fine-grained control over security contexts for
both pods and containers through the spec.podSecurityContext and
spec.securityContext fields respectively.
Note
Changing security contexts can significantly affect the security posture of your PostgreSQL clusters and may prevent pods from starting or operating correctly. Before making changes, review which fields you will override and how they merge with the operator defaults, test changes in a non-production environment, and apply the minimal, well-documented modifications necessary.
Pod Security Context (spec.podSecurityContext ): This allows you
to override the default PodSecurityContext applied to all PostgreSQL
cluster pods. When specified, it will merge with the operator’s default
settings, with your values taking precedence for explicitly set fields.
Example:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-example
spec:
instances: 3
podSecurityContext:
runAsUser: 26
runAsGroup: 26
fsGroup: 26
supplementalGroups: [2000, 3000]
fsGroupChangePolicy: "OnRootMismatch"
Container Security Context (spec.securityContext ): This allows
you to override the default SecurityContext applied to all
containers within the PostgreSQL cluster pods. Like
podSecurityContext , it merges with the operator’s defaults.
Example:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: cluster-example
spec:
instances: 3
securityContext:
allowPrivilegeEscalation: false
# Note: capabilities are not merged with operator defaults.
# If specified, they fully replace any defaults.
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
readOnlyRootFilesystem: true
runAsNonRoot: true
Note
For any fields you don't explicitly set, the operator will apply its secure defaults. This ensures that even partial configurations maintain security best practices.
Note
These fields are particularly useful when working with the Pod Security Standards
restricted profile, which has strict requirements for pod and
container security contexts. As described in Kubernetes Admission Control , it is this
admission chain (not the operator) that enforces such profiles on the
resulting Pods.
Security Context Constraints
When running in an environment that is utilizing Security Context Constraints (SCC)
the operator does not explicitly set the security context of the PostgreSQL cluster pods, but rather allows the pods to inherit the restricted Security Context Constraints that are already defined.
Restricting Pod access using AppArmor
You can assign an AppArmor profile to the postgres ,
initdb , join , full-recovery and bootstrap-controller
containers inside every Cluster pod through the
container.apparmor.security.beta.kubernetes.io annotation. For
example:
kind: Cluster
metadata:
name: cluster-apparmor
annotations:
container.apparmor.security.beta.kubernetes.io/postgres: runtime/default
container.apparmor.security.beta.kubernetes.io/initdb: runtime/default
container.apparmor.security.beta.kubernetes.io/join: runtime/default
Warning
Using this kind of annotations can result in your cluster to stop working. If this is the case, the annotation can be safely removed from the Cluster .
The AppArmor configuration must be at Kubernetes node level, meaning that the underlying operating system must have this option enable and properly configured.
In case this is not the situation, and the annotations were added at the
Cluster creation time, pods will not be created. On the other hand,
if you add the annotations after the Cluster was created the pods in
the cluster will be unable to start and you will get an error like this:
metadata.annotations[container.apparmor.security.beta.kubernetes.io/postgres]: Forbidden: may not add AppArmor annotations]
In such cases, please refer to your Kubernetes administrators and ask for the proper AppArmor profile to use.
Network Policies
The pods created by the Cluster resource can be controlled by
Kubernetes network policies
to enable/disable inbound and outbound network access at IP and TCP level. You can find more information in the networking document .
Note
The operator needs to communicate to each instance on TCP port 8000 to get information about the status of the PostgreSQL server. Please make sure you keep this in mind in case you add any network policy, and refer to the "Exposed Ports" section below for a list of ports used by CloudNativePG for finer control.
Network policies are beyond the scope of this document. Please refer to the Network policies
section of the Kubernetes documentation for further information.
Exposed Ports
CloudNativePG exposes ports at operator, instance manager and operand levels, as listed in the table below:
System |
Port number |
Exposing |
Name |
TLS |
Authentication |
|---|---|---|---|---|---|
operator |
9443 |
webhook server |
webhook-server |
Yes |
Yes |
operator |
8080 |
metrics |
metrics |
No |
No |
instance manager |
9187 |
metrics |
metrics |
Optional |
No |
instance manager |
8000 |
status |
status |
Yes |
Partial (1) |
operand |
5432 |
PostgreSQL instance |
postgresql |
Optional |
Yes |
Status, health, and probe endpoints are unauthenticated. Sensitive endpoints (backup,
pg_controldata, partial WAL archive, and instance-manager upgrade) require the operator’s client certificate, as described in Operator-to-instance authentication (`GHSA-7qwx-x8ff-3px9 ) <Operator-to-instance authentication (GHSA-7qwx-x8ff-3px9 )>`
below.
Operator-to-instance authentication
The operator generates a self-signed ECDSA client certificate in memory
at startup and publishes its SHA-256 public-key fingerprint in the
cluster’s .status.operatorCertificateFingerprint . The instance
manager pins that fingerprint and rejects any call to its sensitive
endpoints (backup, pg_controldata , partial WAL archive, and
instance-manager upgrade) that does not present a matching certificate.
Status, health, and probe endpoints remain unauthenticated.
The certificate is never written to disk and is regenerated on every operator restart, so trust derives from fingerprint pinning rather than CA validation.
This protection has a hard requirement: the status port must be served over TLS, which has been the default since v1.24. A client certificate can only be presented over a TLS connection, so the protected endpoints are reachable by the operator only when the status port uses TLS.
Warning
If the status port is not served over TLS, the instance manager cannot authenticate the operator and permanently rejects every call to its protected endpoints (backup, pg_controldata , partial WAL archive, and instance-manager upgrade) with 401 Unauthorized . This is not a transient condition and will not resolve on its own. It can affect instances created by an operator older than v1.24 (whose status port serves plain HTTP) once their instance manager is upgraded to a version that enforces this authentication: such instances must be rolled out so their Pods are recreated with a TLS-enabled status port. Newly created instances always enable TLS on the status port and are unaffected.
PostgreSQL
The current implementation of CloudNativePG automatically creates
passwords and .pgpass files for the database owner and, only if
requested by setting enableSuperuserAccess to true , for the
postgres superuser.
Warning
enableSuperuserAccess is set to false by default to improve the security-by-default posture of the operator, fostering a microservice approach where changes to PostgreSQL are performed in a declarative way through the spec of the Cluster resource, while providing developers with full powers inside the database through the database owner user.
As far as password encryption is concerned, CloudNativePG follows the
default behavior of PostgreSQL: starting from PostgreSQL 14,
password_encryption is by default set to scram-sha-256 , while
on earlier versions it is set to md5 .
Note
Please refer to the Password authentication
section in the PostgreSQL documentation for details.
Note
The operator supports toggling the enableSuperuserAccess option. When you disable it on a running cluster, the operator will ignore the content of the secret, remove it (if previously generated by the operator) and set the password of the postgres user to NULL (de facto disabling remote access through password authentication).
Note
PostgreSQL may include cleartext role passwords in its logs for some role operations, as mentioned in the PostgreSQL documentation . CloudNativePG ensures that postgres logging (both statement logging and error statement logging) is temporarily suppressed for CREATE/ALTER ROLE operations with passwords, thus preventing any password leakage.
See the Secrets for more information.
You can use those files to configure application access to the database.
By default, every replica is automatically configured to connect in
physical async streaming replication with the current primary
instance, with a special user called streaming_replica . The
connection between nodes is encrypted and authentication is via
TLS client certificates (please refer to the Client TLS/SSL connections page for
details). By default, the operator requires TLS v1.3 connections.
Currently, the operator allows administrators to add pg_hba.conf
lines directly in the manifest as part of the pg_hba section of the
postgresql configuration. The lines defined in the manifest are
added to a default pg_hba.conf .
For further detail on how pg_hba.conf is managed by the operator,
see the Mounting and PostgreSQL Configuration of the documentation.
The administrator can also customize the content of the
pg_ident.conf file that by default only maps the local postgres user
to the postgres user in the database.
For further detail on how pg_ident.conf is managed by the operator,
see the Mounting and PostgreSQL Configuration of the documentation.
Note
Examples assume that the Kubernetes cluster runs in a private and secure network.
Schema resolution and search_path hardening
A user with privileges on a database can plant objects (functions,
operators, tables, or types) in a writable schema such as public and
change the database- or role-level search_path (for example with
ALTER DATABASE ... SET search_path or
ALTER ROLE ... SET search_path ). A privileged session that later
connects to that database inherits the tenant-controlled search_path
, so an unqualified reference in one of its queries could resolve to the
planted object instead of the intended one. This is a
privilege-escalation vector analogous to CWE-426 (Untrusted Search Path) , and the same
class of issue as the well-known
CVE-2018-1058 .
To prevent this, CloudNativePG pins the search_path on every
connection it opens to PostgreSQL to a fixed value of
pg_catalog, public, pg_temp , regardless of any search_path
configured on the database or the connecting role:
pg_catalogis searched first, so a built-in object always takes precedence over a same-named object planted in another schema;pg_temp(the session-private temporary schema) is searched last rather than first, so it cannot shadow relations or data types.
In addition, the SECURITY DEFINER lookup function used by the
PgBouncer integration is created with its own pinned search_path ,
and the monitoring queries run inside a transaction whose
search_path is pinned as described in the Monitoring Backup Progress .
Note
User-authored SQL — postInitSQL /postInitApplicationSQL /postInitTemplateSQL during bootstrap, and the post-import queries of a logical import — runs with the standard "$user", public resolution so that it keeps behaving as it would in a plain PostgreSQL session. Schema-qualify object references in those scripts if you need them to be independent of the search_path .
Storage
CloudNativePG delegates encryption at rest to the underlying storage class. For data protection in production environments, we highly recommend that you choose a storage class that supports encryption at rest.