PostgreSQL 18.4, 17.10, 16.14, 15.18, and 14.23 are out as of May 14, 2026. The release fixes eleven security issues and more than sixty bugs. That is not a typo. Eleven CVEs is the largest single-release security batch I can remember, and three of them are CVSS 8.8 with practical exploitation paths. Patch this week. If you can patch tomorrow, patch tomorrow.

The release announcement is here. What follows is the version that explains which of these you actually need to think about, and why.

The Three That Matter

CVE-2026-6473 — Integer wraparound undersizes allocations

CVSS 8.8, all supported branches, core server. Multiple server features allow an application-input provider to wrap a size computation, which causes the backend to allocate a buffer too small for what it then writes into. The result is an out-of-bounds write and a SIGSEGV. The credit line on this one is ten people from at least three different research groups, which tells you everything you need to know: several independent fuzzers converged on the same class of bug at roughly the same time. There are probably more of these in the same neighborhood. The fix landed, but the neighborhood is suspicious.

This is the headline. Treat it as such.

CVE-2026-6477 — libpq lo_* stack overwrite, courtesy of a hostile server

CVSS 8.8, all supported branches, client-side. The bug is in libpq’s use of PQfn(..., result_is_int=0, ...) inside lo_export(), lo_read(), lo_lseek64(), and lo_tell64(). That call writes server-determined data into a client-side stack buffer of unspecified size. It is, functionally, gets(). A hostile server superuser can hand back an arbitrarily long response and stomp the client’s stack.

Now read that paragraph again with this fact attached: pg_dump calls lo_read(). So does psql’s \lo_export. Which means a pg_dump against a server you do not fully trust can corrupt the dumping client’s memory.

If that sounds familiar, it is because we have been here before. CVE-2024-7348 (pg_dump relation replacement). CVE-2025-8714 and CVE-2025-8715 (pg_dump superuser-from-origin RCE via newline in object names). This is the third time in three releases that the right answer to “what is the threat model for pg_dump?” has had to be revised downward. The cumulative answer is now clear: do not run pg_dump against a server unless you would also run psql against that server as a superuser. The two binaries trust the origin equally, and equally hard.

CVE-2026-6475 — pg_basebackup and pg_rewind follow symlinks

CVSS 8.8, all supported branches, client-side. pg_basebackup --format=plain and pg_rewind will follow symlinks placed by a hostile origin superuser, and will happily overwrite files outside the data directory. The example in the advisory is ~/.bashrc of the OS account running the backup, which is precisely the kind of thing that hijacks the operating system account on next login.

The advisory carries a real caveat: if you start the server immediately after the backup, you have already lost — shared_preload_libraries from a hostile origin owns you the moment postmaster comes up. So the practical exposure window is the interval between the backup and the server start. Snapshotting a freshly-built basebackup volume. Moving the data directory to a different host. Anything that touches the filesystem between pg_basebackup finishing and the next postmaster start. If your workflow includes any of those steps, this CVE has your name on it.

The Smaller Print

The remaining eight CVEs are lower severity, but a few of them are still worth ten seconds of your attention.

CVE-2026-6478 is a covert timing channel in MD5 password comparison that lets an attacker recover password hashes. SCRAM-SHA-256 is not affected — and SCRAM has been the default since PG14. But “default since PG14” does not mean “in use everywhere,” because clusters that were pg_upgrade-d from PG13 or earlier still have MD5 hashes baked in for any role that never changed its password after the upgrade. If you do not know whether you still have MD5 hashes, run SELECT rolname FROM pg_authid WHERE rolpassword LIKE 'md5%'; on your production cluster. If that returns rows, you have homework that is unrelated to this CVE and that has been waiting for you for years.

CVE-2026-6637 is a stack buffer overflow plus SQL injection in contrib/refint. The refint module is a 1990s-vintage referential-integrity implementation that was obsoleted the moment real foreign keys shipped, and nobody should still have it loaded. Some of you do. You know who you are. Stop.

CVE-2026-6479 is uncontrolled recursion in the SSL/GSS negotiation path, which produces sustained DoS via an unauthenticated connection. The credit line on this one reads “Calif.io in collaboration with Claude and Anthropic Research,” which appears to be the first time a CVE attributed (in part) to LLM-assisted discovery has landed in the PostgreSQL security tree. I have opinions about how excited we should be about that. They can wait for another post.

CVE-2026-6472 closes a missing privilege check in CREATE TYPE for multirange auxiliary types, reported by Jelte Fennema-Nio. CVE-2026-6476 is SQL injection in pg_createsubscriber via the subscription name. CVE-2026-6638 is SQL injection in ALTER SUBSCRIPTION ... REFRESH PUBLICATION via table name, which fires on the publisher at the next refresh. CVE-2026-6474 is a format-string leak in timeofday() via crafted timezone strings. CVE-2026-6575 is a PG18-only buffer over-read in pg_restore_attribute_stats() when array lengths do not match.

Any one of those would be a reasonable headline in a normal release. They are not the headline this time.

The Bugs You Need to Know About

Sixty-plus bug fixes is more than I want to enumerate. Here are the ones that fix silently-wrong behavior, which is the category that matters:

Incorrect results from queries that combine a nondeterministic collation with a unique index. This is exactly the kind of bug that does not announce itself. The query returns rows; some of them are wrong; downstream analytics build dashboards on top of them; and a quarter later somebody wonders why the count is off by 3%. If you use CREATE COLLATION ... (deterministic = false) anywhere, patch and then re-run any reports whose answers you have ever been uncertain about.

DEFERRABLE INITIALLY DEFERRED foreign keys silently lose deferrability if you toggle them NOT ENFORCED and back to ENFORCED. After the patch, an affected constraint stays broken until you toggle it again. The release notes are explicit about the workaround. If you have used NOT ENFORCED on a deferrable FK — and if you are reading this you probably know if you have — set it NOT ENFORCED and back to ENFORCED after the upgrade.

MERGE now reports a serialization failure correctly under REPEATABLE READ and SERIALIZABLE when it encounters a concurrently-updated tuple. Before this patch, those isolation levels could produce semantically wrong results from MERGE without complaining. If your application uses MERGE under non-default isolation, that application’s behavior has just changed, possibly in ways you will only notice in production.

Stuck logical replication slot synchronization worker processes no longer block standby promotion. This was a real-world failover-blocker on 17 and 18. If you have ever had a failover hang for reasons that did not show up in any obvious log line, this is plausibly the reason.

Free space map changes are now persisted during recovery. A standby that has been replaying for a long time without flushing FSM updates could, after promotion, see bloat grow in surprising ways. This is the kind of bug whose impact you would only notice weeks later.

The remaining fixes are useful but not behaviorally critical. The release notes have the full list. Read them.

Other Things in the Box

tzdata updates to 2026b. British Columbia goes to year-round UTC-07 starting November 2026 — call it “permanent MST,” because that is the abbreviation the maintainers have chosen to assume going forward. If you have application code that does anything clever with America/Vancouver timestamps in or after November, look at it before November. There is also a historical correction for Moldova back to 2022, which is unlikely to affect anyone, but here we are.

And one administrative note: PostgreSQL 14 reaches end of life on November 12, 2026. That is six months from now. If you are on 14 in production, you have one more minor release after this one before you are running unsupported PostgreSQL. Plan accordingly.

The Short Version

Three 8.8 CVEs with practical exploit paths. Two of them — pg_dump stack corruption and pg_basebackup symlink follow — assume a hostile server, which is exactly the kind of threat model people insist they do not have until they do. Two silent-data-correctness bug fixes (nondeterministic collations, MERGE under serializable). One MD5-password disclosure that has been sitting in your auth tables since you upgraded from 13. And contrib/refint still exists, apparently.

Patch.