PostgreSQL has patched a vulnerability that sat unnoticed in its logical decoding subsystem for twelve years. CVE-2026-6471, dubbed PostGREShell, lets any role holding the REPLICATION attribute escalate to arbitrary code execution as the operating-system account running the database server — a path that ends in full host takeover and a persistent backdoor, not just a compromised database.
What Happened
Logical decoding, introduced in PostgreSQL 9.4 (2014), lets a client stream row-level changes out of the write-ahead log by selecting an “output plugin” — a shared library the server loads via dlopen(). The bug is a missing-authorization flaw: PostgreSQL never restricted which libraries a replication-privileged role could name as that plugin. Any file visible to the OS user running postgres — including one an attacker planted via an unrelated write primitive, a writable extension directory, or a staging path used by a backup tool — could be handed to CREATE_REPLICATION_SLOT ... LOGICAL <plugin_name> and loaded straight into the server process.
Because the loaded library executes as the database server’s OS user, not as a sandboxed SQL role, this converts a purely logical, row-streaming privilege into native code execution on the host. From there, an attacker can install a persistent backdoor, pivot to the OS, and quietly tamper with WAL processing to erase the evidence trail.
Technical Details
- CVE: CVE-2026-6471
- CVSS: 7.2
- Root cause: Missing authorization in logical decoding output-plugin selection — no allowlist governed which shared libraries a
REPLICATION-privileged role could load - Requirements to exploit: A role carrying the
REPLICATIONattribute, a server running withwal_level = logical, and a file path the server’s OS user can read - Affected versions: Every PostgreSQL release from 9.4 through 18 that predates the fix (confirmed reachable on 18.2); this covers essentially every production PostgreSQL deployment running logical replication
- Fixed versions: 18.6, 17.11, 16.15, 15.19, 14.24 (released August 13, 2026)
- Fix mechanism: A new server parameter,
output_plugin_libraries, allowlists which libraries may be loaded as logical decoding output plugins — defaulting topgoutput, test_decoding - Public exploit status: No proof-of-concept was public as of September 4; treat that as a narrow window, not a reason to deprioritize patching
Who’s Affected
The REPLICATION attribute is not a rare, tightly-held grant — it’s routine plumbing. Backup tools, standby/replica servers, change-data-capture pipelines (Debezium and similar CDC connectors), and monitoring or ETL systems are commonly issued replication credentials as a matter of course, often with broader trust than a typical application role gets. Any environment where that credential is shared across a team, embedded in a CI job, cached in a sidecar, or held by a third-party SaaS integration effectively hands out a code-execution primitive on the database host, not just read access to change streams.
Managed PostgreSQL (RDS, Cloud SQL, Azure Database for PostgreSQL, Aurora) mitigates some of the OS-level blast radius depending on how the provider sandboxes the server process, but self-hosted PostgreSQL — on bare metal, VMs, or in containers/Kubernetes as a StatefulSet — gets the full impact: code execution as the account that owns the data directory, WAL files, and often the container’s only meaningfully privileged process.
What To Do Right Now
- Patch immediately to 18.6, 17.11, 16.15, 15.19, or 14.24, whichever branch you track. This is a straightforward point-release upgrade, not a major-version migration.
- Audit who holds
REPLICATION. RunSELECT rolname FROM pg_roles WHERE rolreplication;and confirm every credential on that list is one you actually issued and still need — not a leftover from a decommissioned CDC pipeline or a shared service account. - After patching, review
output_plugin_libraries. The default (pgoutput, test_decoding) is safe for standard logical replication; only widen it if you have a specific, audited output plugin that needs it. - If patching is delayed, treat every
REPLICATION-privileged credential as equivalent to root on the database host and restrict network reachability to those roles accordingly. - Hunt for compromise on servers that ran with
wal_level = logicaland unpatched PostgreSQL: check for unexpected shared libraries in paths readable by thepostgresuser, unfamiliar replication slots, and anomalous child processes spawned by the postmaster.