PgBouncer 1.26.1 fixes identity changes during SCRAM authentication
A second startup message could let one SCRAM user impersonate another. PgBouncer also fixes two configuration-dependent denial-of-service flaws and restores an explicit search_path override.
A client that knew one SCRAM user's password could authenticate as another user through affected PgBouncer versions. The trigger involved sending a second startup message during authentication while connecting to a nonexistent database. PgBouncer 1.26.1, released on October 14, fixes this as CVE-2026-107350. The PostgreSQL announcement also identifies two denial-of-service vulnerabilities reachable without authentication under particular configurations.
This is a significant distinction for a connection pooler. The authentication exchange has to establish which identity proved knowledge of a password. Handling another startup message during that exchange allowed the process to produce the wrong result. The problem exists in PgBouncer's handling of the protocol, so updating only the PostgreSQL server does not replace the affected component.
I still default to PostgreSQL for relational systems after decades of production use. Its documented behavior is part of that confidence, and a pooler introduces another implementation whose behavior matters. This release makes that dependency concrete. A correct database permission model cannot compensate for an intermediary accepting the wrong identity before it opens or assigns the database connection.
The attacker needs a valid SCRAM identity
The PgBouncer changelog gives the affected range as 1.17.0 through 1.26.0. The attacker must know the password of a user listed in auth_file. Both that user and the impersonated user must use SCRAM authentication. The target identity can come from auth_file or auth_query, and can include an administrator or backend superuser.
Those conditions define a more specific exposure than an unauthenticated login bypass. Someone needs a working credential, but it can belong to a less privileged user. The vulnerability then permits authentication as a different SCRAM user. The permission difference between the known account and the target account is what makes the failure consequential for installations that deliberately separate application and administrative roles.
The nonexistent database is part of the documented trigger. A client does not have to be conducting an ordinary successful login to one of the configured databases to reach this faulty exchange. That matters when interpreting failed connection attempts. A rejection associated with an invalid database name does not by itself establish that the authentication state machine never processed dangerous input.
The changelog locates the fault in processing a second StartupMessage while SCRAM authentication is already in progress. At that point, the connection is already establishing an identity through an ongoing exchange. A second startup message must not be allowed to turn that exchange into proof for another user. This is the state-transition rule illustrated by the fix, without needing to reproduce an attack packet sequence.
Configuration-based exposure assessment remains useful for prioritizing the rollout. An installation using a different authentication arrangement does not automatically satisfy the advisory's conditions. However, the published correction is the release upgrade, and the advisory includes more than one route for obtaining the target identity. Restricting attention to users directly stored in the authentication file would omit targets supplied through auth_query.
A startup option can occupy the process indefinitely
CVE-2026-107349 affects PgBouncer 1.20.0 through 1.26.0. An unauthenticated client can supply an empty option name in the startup options parameter, causing an infinite loop. The changelog gives -c= as an example of the malformed option. The exploit condition requires ignore_startup_parameters to be nonempty without including options.
This condition makes the actual configuration relevant. An operator cannot infer exposure merely from having changed some startup parameter handling in the past. The precise question is whether the current ignored-parameter list is nonempty and lacks the options entry. The flaw is in parsing a particular malformed input under that configuration, rather than in the normal meaning of a valid startup setting.
The reported consequence is that PgBouncer spins on a CPU core and stops serving clients. A denial-of-service fault in the pooler can therefore affect connections unrelated to the client that sent the bad startup message. Authentication does not protect this path because the message arrives before the client has established a user identity. Tests limited to successfully authenticated traffic would not exercise that boundary.
I value predictable failure handling in the software around PostgreSQL as much as in schema changes inside it. Here, the required behavior is straightforward. Invalid startup input must terminate or reject the relevant exchange without preventing service for other clients. The changelog supplies both the malformed-input condition and the configuration needed to reach the old loop, which makes the diagnosis more useful than a generic warning about suspicious clients.
Packet size changes the second denial-of-service exposure
CVE-2026-107348 is another infinite loop, with a different cause and affected range. PgBouncer 1.21.0 through 1.26.0 has an integer overflow in packet buffer growth logic. A client can trigger it by declaring a packet length greater than 2^31 when the configured maximum packet size permits that declaration. The changelog says it is reachable before authentication starting in 1.23.0.
The default max_packet_size is 2147483647 and is not affected by this particular vulnerability. The exploitable setting is 2147483649 or higher. Those exact values matter because the issue depends on crossing an integer boundary. A description that simply says large packets are dangerous would lose the difference between the default configuration and the nondefault exposure the project identifies.
The changelog connects this fault to CVE-2026-6668, fixed in 1.26.0, as the same class of bug in a different buffer implementation. That history explains why a recent update can still leave a related failure. Correcting one calculation does not prove that every buffer growth path applies the same bounds correctly. The new advisory identifies the remaining implementation and the configuration that makes it reachable.
The two denial-of-service issues should therefore retain separate entries in an assessment. One depends on the ignored startup parameter list, while the other depends on an unusually high packet-size limit. Combining them into a single statement about malformed startup traffic would make it harder to explain why one installation meets a condition and another does not. Both receive fixes in 1.26.1.
Parameter tracking changed in the preceding release
The release includes a nonsecurity correction involving search_path. PgBouncer 1.26.0 began tracking all parameters reported by PostgreSQL by default. The changelog specifically identifies search_path on PostgreSQL 18 and later, and default_transaction_read_only on PostgreSQL 14 and later. Previously, setting these in transaction pooling mode could affect another client that later reused the same server connection.
Tracking is intended to manage those session-state differences, but 1.26.0 also made an explicit ignored search_path setting ineffective. Version 1.26.1 gives ignore_startup_parameters precedence over tracked parameters. The following setting once again restores the 1.25 behavior of ignoring search_path, according to the release notes.
ignore_startup_parameters = search_path
The project says several bugs involving search_path tracking have been reported and will be addressed in a later release. As of October 14, restoring the explicit override is the change available here. That statement does not establish that every tracking issue is corrected in 1.26.1. Operators using the override need to understand its older behavior as well as the reason tracking was introduced.
This is an operational compatibility question alongside the security update. A configuration file can contain the same line across two versions while the precedence rules determine whether it takes effect. The correction restores the meaning of an explicit operator choice, which is a separate result from correcting SCRAM authentication or rejecting malformed packets.
For an installation moving from an older version, the preceding 1.26.0 changes also matter to the restart procedure. Its changelog removes the deprecated -R online restart mechanism and directs users toward rolling restarts with so_reuseport. This is relevant to deploying the security fix because a procedure based on the removed mechanism cannot be assumed to remain available simply because the destination is a patch release within the 1.26 series.
The combination also explains why successful connection tests give incomplete evidence for this update. An ordinary login does not send a second startup message during authentication or exercise the malformed option parser. Those failures concern transitions and rejection paths. Their correction belongs in protocol tests that preserve the relevant input conditions, alongside the normal application's connection tests.
The release notice provides the corrected source download and its checksum. The useful deployment record identifies the PgBouncer version and the effective startup-parameter and packet-size settings. It also retains the authentication sources involved, since the SCRAM bypass conditions distinguish the account whose password is known from the identity that could be impersonated.