The cuckoo doesn’t build a nest: it lays its egg in another bird’s, which incubates and feeds it as its own. Nobody checks what’s inside the egg, only that it’s in the nest. Something similar has been happening in PostgreSQL for 22 years: some bytes placed as one data type that, later on, the server reads as if they were another.
Mehmet Ince explains it in the third part of a six-part series on the risks of managed Postgres. The bug is CVE-2026-6460, with a CVSS score of 8.8, and a user with minimal privileges is enough to crash the server and, according to the author, get as far as running code.
What happens
The idea, without going into the exploit details, is simple to explain:
- You create a composite type (a row type, with its attributes) and prepare a statement that builds a value of that type with a
uuidattribute. - With
ALTER TYPEyou change that attribute’s type to a different one. - The prepared statement keeps using the old bytes, which nobody has rewritten, but now the server interprets them with the new type.
If the new type is bytea, the function that converts it to text interprets those bytes as a pointer to an “expanded object” (an in-memory representation Postgres uses to work with large values) and calls its methods. With a null pointer, the process crashes. With the same confusion applied to an array, you can leak a memory address as if it were a number. Put the two together and, the author explains, you can redirect that call and end up running system commands.
Why 22 years? Because the ability to change a column’s type arrived in a commit dated May 5, 2004. Expanded objects, which turn the confusion into something exploitable, arrived in 2015. Two pieces that are reasonable on their own and, together, open the door.
The managed providers
What struck me most isn’t the bug itself but the author’s line: “I haven’t seen any vendor who is not affected by this vulnerability!”. He found it in early August and privately notified Databricks, Google (AlloyDB), Supabase, AWS (Aurora and RDS), Azure, Ubicloud and ClickHouse. Some applied their own mitigations before the official patch came out.
On managed Postgres you’re not a superuser: the provider gives you a trimmed-down role precisely so you can’t get out of your database into the system. A bug that only needs a regular user to run code skips right over that boundary, and on a shared service that’s the worst thing that can happen.
The series has more to it. The first part covers memory corruption in address_standardizer, an extension that ships with PostGIS, exploited on NeonDB, Supabase and Xata. His thesis is that there is no such thing as an extension sandbox: a memory bug in an extension is a memory bug in the server itself, and since every provider offers the same extensions, a single bug hits many companies at once. For those of us who work with geospatial data, PostGIS isn’t an optional extra, so this one hits close to home.
What to do
Upgrade. The fixed versions were released this week:
| Branch | Fixed version |
|---|---|
| 18 | 18.7 |
| 17 | 17.12 |
| 16 | 16.16 |
| 15 | 15.20 |
| 14 | 14.25 |
13 and earlier no longer get patches, so if you’re still on one of them, it’s time to migrate. And it’s not an upgrade just for this bug: the announcement includes more than 40 CVEs, several scored 8.8 (another type confusion in PL/pgSQL, a use-after-free in dblink, logical replication writing to the subscriber’s catalog…). To check which version you’re on:
SELECT version();
If you use a managed service, the provider will usually apply it for you, but it’s worth checking that the minor version has actually gone up rather than taking it for granted. And if you run your own Postgres with users you don’t fully trust (third-party apps, shared environments, analytics accounts…), don’t wait for the next maintenance window.
I’ll stick with the series’ underlying point: we’ve made Postgres the default database for half the world, with dozens of providers offering it as a service and the same extensions on all of them. That’s great until a bug like this shows up, one that isn’t in a particular provider but in the code they all share.




