Date: 4 May 2026
Severity: Pre-authentication SQL execution. High impact in narrow configurations.
Action: Verify your pgBouncer version and configuration today. Patch path is straightforward.
Summary
pgBouncer 1.25.0 and earlier contain a vulnerability that allows an unauthenticated attacker, with network access to the pooler, to execute arbitrary SQL during the authentication exchange. The vulnerability is fixed in pgBouncer 1.25.1, released 3 December 2025. The CVE identifier is CVE-2025-12819.
The vulnerability is not universal. It only triggers when a specific combination of settings is configured. Most default deployments are not exposed. Some non-default deployments — including, notably, those built around Citus or PostgreSQL 18 conventions — almost certainly are.
Threat Model
The attacker needs only network reachability to the pgBouncer port. They do not need:
- a valid PostgreSQL username or password
- TLS client certificates
- access to
userlist.txt - prior authentication of any kind
What they need is the ability to open a TCP connection to pgBouncer and send a crafted PostgreSQL StartupMessage. That is it.
The exploit vector is the search_path parameter inside the StartupMessage. When track_extra_parameters includes search_path, pgBouncer carries the client-supplied value across into the connection that runs auth_query against the backend. If auth_query is configured without fully-qualified object names — which is the default — the attacker-controlled search_path determines which schema the resolver consults when running the query. From there, a hostile schema containing functions, operators, or tables with names that shadow the ones expected by auth_query gets the attacker’s SQL executed under the privileges of auth_user.
auth_user is typically given limited rights to pg_authid or to a security-definer wrapper. It is not, however, an unprivileged role. SQL execution as auth_user is sufficient to read other users’ password hashes, examine catalog metadata, and — depending on local hardening — pivot further into the cluster.
The exploit happens before any authentication completes. There is nothing in pgBouncer’s logs that will resemble a failed login. The first observable artifact is whatever the injected SQL did.
Who Is Vulnerable
A deployment is vulnerable if and only if all three of the following are true:
track_extra_parametersincludessearch_pathauth_useris set to a non-empty valueauth_queryis configured without fully-qualified (schema-qualified) object names
The first condition is the rarest. track_extra_parameters is a non-default setting and was added largely to support workloads where the application sets search_path per-connection and expects pooled sessions to honor it. The two real-world contexts where you should expect this to be set are:
- Citus deployments, which historically rely on per-tenant
search_pathand configure pgBouncer accordingly. - PostgreSQL 18 deployments that follow the newer conventions for protocol parameter passthrough.
Generic application stacks running stock pgBouncer 1.x without modifying track_extra_parameters are not exposed to the unauthenticated SQL execution. They should still patch on the normal cadence — not all of the bugs fixed in 1.25.1 are exotic — but they are not in emergency territory.
Remediation
In order of preference:
1. Upgrade to pgBouncer 1.25.1. This is the only fix that closes the vulnerability cleanly. On Debian and Ubuntu the security backports are available. On RHEL/Rocky the PGDG packages have been refreshed. For CloudNativePG users, the operator already defaults the bundled pooler to 1.25.1; verify your Pooler resources have rolled to the new image. For Azure Database for PostgreSQL, Microsoft has rolled the upgrade to managed pgBouncer in the March maintenance window. For RDS Proxy users, RDS Proxy is not pgBouncer and is not affected.
2. If you cannot upgrade today, remove search_path from track_extra_parameters. This is the precise mitigation: it prevents pgBouncer from carrying the attacker-controlled value across the auth exchange. Applications that legitimately need per-tenant search_path will need to set it after the connection is established (e.g., via a SET search_path after checkout from the pool) rather than via the StartupMessage. Test this against your application before deploying broadly.
3. Schema-qualify everything in auth_query. If your auth_query reads pg_authid or a security-definer wrapper function, qualify it as pg_catalog.pg_authid and your_schema.your_wrapper(...). This is good practice independent of CVE-2025-12819 and should be the standing configuration. Doing this alone, without addressing track_extra_parameters, narrows the exposure but does not eliminate it — there are still operators and functions an attacker-controlled search_path can shadow.
If you operate Citus, treat this as urgent. The Citus configuration footprint is the one most likely to satisfy all three vulnerable conditions simultaneously.
What to Check Today
Run this on each pgBouncer host:
1 pgbouncer --version
2 grep -E '^(track_extra_parameters|auth_user|auth_query)' /etc/pgbouncer/pgbouncer.ini
If the version is below 1.25.1, and track_extra_parameters mentions search_path, and auth_user is set, you are exposed. Patch or apply the configuration mitigation today.
If the version is below 1.25.1 and the other two conditions do not apply, you should still upgrade — there are unrelated bug fixes in 1.25.1 that you want — but the urgency is different.
Forensics
There is no clean log signature for a successful exploit because the SQL runs as part of an attacker connection that pgBouncer treats as a normal authentication attempt. If you have reason to suspect exposure during the window between November 2025 and the day you patched, look for:
- unexplained reads against
pg_authidfrom theauth_userrole inpg_stat_statementshistory - recently created functions, operators, or tables in schemas writable by
auth_useror by any role whose privilegesauth_usercan reach - audit-extension records (
pgaudit, vendor-specific audit logs) showing SQL executed underauth_useroutside of the normalauth_querytext
Absence of evidence is not evidence of absence here. Patch first, investigate after.
Recommended Posture Going Forward
Treat auth_query as security-critical SQL. Schema-qualify it, and audit it on the same cadence as your application code. Treat track_extra_parameters as a privileged setting and review every parameter you carry across the pool boundary. Anything that can flow from an unauthenticated client into a backend SQL context is, definitionally, attack surface.
We are available to review your pgBouncer configuration on request. For urgent assistance, reach out via the standard PGX channel.