February 9, 2023·4 min read·engineeringpostgresqlsecuritylibpqreplication

PostgreSQL 15.2 fixes a client error path that exposes memory

CVE-2022-41862 concerns libpq clients negotiating Kerberos encryption. The same maintenance release repairs generated-column and replication correctness.

An error message received before a connection becomes trustworthy can itself expose client memory. PostgreSQL 15.2 closes that failure in libpq during negotiation of GSSAPI transport encryption. A malicious server supplies an unterminated string, and the client copies bytes beyond the intended message into its own error report. The final disclosure depends on where the application sends that report.

The February 9 release announcement identifies the issue as CVE-2022-41862. PostgreSQL releases 15.2, 14.7, 13.10, 12.14 and 11.19 arrive together, with one security fix and more than 60 bug fixes across the release set. The stated security vulnerability affects versions 12 through 15. Including 11.19 in the maintenance announcement does not put version 11 inside that affected range.

I value PostgreSQL for the precision of its documented behavior. This defect makes that precision necessary outside SQL execution, where a connection library processes remote data before the application has an authenticated database session.

A missing terminator changes the error report

The 15.2 release notes explain the faulty operation. During GSSAPI setup, libpq accepts a server error message without ensuring that it ends with a zero byte. Copying it as a terminated string continues into following application memory until another zero byte appears. The fix terminates the server message correctly before that copy.

The announcement identifies two possible senders of the crafted message. One is a modified, unauthenticated server. The other is an unauthenticated attacker between the client and server. A legitimate database account is therefore not a prerequisite in the described attack. The relevant input reaches the client during establishment of transport encryption.

There are also client prerequisites. The libpq application must have a Kerberos credential cache and must not explicitly disable gssencmode. Those conditions matter when assessing exposure. Describing this as a vulnerability in every PostgreSQL query would obscure the connection path that actually contains the bug.

Receiving the malformed message does not automatically send memory back over the connection. The extra bytes enter the client error report. Disclosure occurs if the calling application makes that report available to the attacker, perhaps through an application error response. The release announcement leaves that last step conditional because applications handle connection failures differently.

The project also distinguishes demonstrated behavior from unresolved consequences. Its announcement neither confirms nor rules out arranging a crash or obtaining particularly valuable confidential bytes. The release notes describe a small probability of a crash from reading beyond available memory. That uncertainty is a reason to preserve the stated scope, rather than inventing a reliable extraction method the sources do not supply.

The deployed client library matters

The vulnerable code belongs to libpq. Updating only a remote database server does not establish that a separate application process now loads the repaired client library. Deployment inventories need to distinguish the server binaries from the library used by each affected application. That follows directly from where the release notes locate the faulty copy.

Error handling deserves the same attention. Applications that return complete database connection errors to callers create a different disclosure path from applications that retain those errors privately. Restricting error visibility can affect the final attacker access, but it does not repair the invalid read. The corrected library removes the memory over-read at its source. It fixes the error-processing path before application reporting policy becomes relevant.

The release credits Jacob Champion for reporting the problem. Its mechanism is small enough to describe without speculative exploit code, and a configuration example would not demonstrate the missing terminator. The significant change is the length boundary enforced inside the client implementation.

Generated columns expose action-dependent state

A separate correctness fix concerns MERGE and generated columns. Before this update, an initial row-level UPDATE action could mark some generated expressions unnecessary because their dependencies were absent from the update target. Later INSERT actions in the same command could then fail to compute those generated columns. The release notes attribute that correction to Dean Rasheed.

That failure crosses the lifetime of an internal decision. Whether a generated expression needs recomputation depends on the action being performed. An insertion cannot inherit an update-specific decision that some existing values remain valid. The maintenance release repairs this interaction within one command, rather than introducing a different application-level merge policy.

Another generated-column fix concerns partitioned tables and inheritance. PostgreSQL must account for generated columns that exist only in a child, and for child expressions whose dependencies differ from their parent expressions. Computing required updates from only the parent definition misses those cases. The release notes name both cases explicitly, which helps explain why the correction belongs in maintenance even when the parent schema appears unchanged.

My preference for transactional schema behavior does not remove the need for these corrections. Applications still depend on each supported expression and statement producing the documented result after the schema has been created.

Replication cleanup and output have separate corrections

The replication changes address both retained state and transmitted data. An invalidated logical replication slot could continue determining the oldest catalog transaction boundary after exceeding max_slot_wal_keep_size. That could prevent removal of dead catalog tuples indefinitely. Ignoring invalidated slots for that calculation allows catalog cleanup to proceed according to the remaining valid requirements.

The pgoutput plugin also failed to honor a publication column list for UPDATE and DELETE events. The release notes say PostgreSQL's built-in receiver tolerated the extra columns, while other receivers might become confused. Even with the built-in receiver, sending the extra data wasted bandwidth. Compatibility with one receiving implementation did not make the emitted column set correct.

These are independent reasons to apply the maintenance release alongside the security correction. PostgreSQL describes minor updates as cumulative and says this update does not require a dump and reload or pg_upgrade. For an existing 15.x installation, the stated procedure replaces the binaries after shutdown. Installations skipping earlier updates still need the earlier release notes, because any additional post-update requirements remain applicable when moving directly to 15.2.