Introduction
A single unauthenticated connection to a PostgreSQL server can crash a backend process with nothing more than a carefully sequenced series of SSL and GSS negotiation messages. CVE-2026-6479, disclosed on May 14, 2026, is a flaw in how PostgreSQL handles encryption negotiation during connection startup. An attacker can use it for sustained denial of service, and it carries a CVSS 3.1 base score of 7.5.
PostgreSQL is the fourth most popular database management system globally, with a DB Engines score of 682.68 as of May 2026. Because it is so widely used, this vulnerability has a broad blast radius across cloud infrastructure, SaaS platforms, and enterprise deployments.
Technical Information
Root Cause: Uncontrolled Recursion in ProcessStartupPacket()
The vulnerability is classified under CWE-674 (Uncontrolled Recursion) and lives in the ProcessStartupPacket() function, which handles the initial handshake between a connecting client and the PostgreSQL backend. During this phase, the server processes startup packets that may include requests to negotiate SSL or GSS encryption.
The flaw is architectural. When the server received an SSL or GSS negotiation request, ProcessStartupPacket() handled it by calling itself recursively, so each negotiation attempt pushed a new stack frame onto the call stack. No counter, depth limit, or state flag tracked how many negotiation attempts had occurred within a single connection.
A malicious client could exploit this by alternating between SSL and GSS encryption requests. Each request would be rejected (assuming the server does not support or has disabled the requested protocol), but the function would recurse anyway. By sending these requests indefinitely, the attacker could grow the call stack without bound until it overflowed and crashed the connected backend process.
Attack Flow
The exploitation sequence is straightforward:
- The attacker opens a raw socket connection to the PostgreSQL server (either AF_UNIX or TCP).
- The attacker sends an SSL negotiation request. The server rejects it (responding with
'N') and recurses intoProcessStartupPacket(). - The attacker then sends a GSS negotiation request. The server rejects it and recurses again.
- The attacker repeats steps 2 and 3, alternating between SSL and GSS requests.
- Each iteration adds another stack frame. After enough iterations, the call stack overflows and the backend process crashes.
Attack Surface Depends on Configuration
Whether the attack works over the network depends on the server's encryption configuration:
| Connection Type | SSL and GSS Status | Vulnerability Status |
|---|---|---|
| AF_UNIX socket | Any configuration | Vulnerable to denial of service |
| TCP socket | Both SSL and GSS disabled | Vulnerable to denial of service |
Local socket access (AF_UNIX) is always a risk, whatever the encryption settings. Network-based attacks over TCP become possible when administrators have disabled both SSL and GSS, because in that configuration the server rejects both negotiation types but still processes each one recursively.
Patch Information
The PostgreSQL Global Development Group shipped a fix for CVE-2026-6479 on May 14, 2026, across all supported major branches: 18.4, 17.10, 16.14, 15.18, and 14.23. Michael Paquier wrote the patch and Noah Misch committed it (commit f7a191f53 on the main/18 branch, with backport variants such as 66cf26b9e for branches where the affected code lived in a different file).
The Fix: Recursion Replaced with Iteration
The fix is simple. It replaces the recursive calls with an iterative loop using a goto retry label. Instead of calling ProcessStartupPacket() again (pushing another frame onto the stack), the function now updates its local ssl_done and gss_done flags in place and jumps back to a retry: label at the top of the function body. The stack depth stays constant no matter how many negotiation messages a client sends.
The core change is in src/backend/tcop/backend_startup.c in the v18 variant. Older branches apply the identical logic in src/backend/postmaster/postmaster.c.
For the SSL negotiation path, the recursive call:
- return ProcessStartupPacket(port, true, SSLok == 'S');
was replaced by:
+ ssl_done = true; + if (SSLok == 'S') + { + /* + * We are done with SSL and negotiated correctly, so consider the + * same for GSS. + */ + gss_done = true; + } + goto retry;
The patch applies the same transformation to the GSS negotiation path:
- return ProcessStartupPacket(port, GSSok == 'G', true);
became:
+ gss_done = true; + if (GSSok == 'G') + { + /* + * We are done with GSS and negotiated correctly, so consider the + * same for SSL. + */ + ssl_done = true; + } + goto retry;
When a negotiation succeeds (e.g., SSLok == 'S'), the function also marks the other protocol as done. Once SSL encryption has been established, there is no reason to entertain a later GSS encryption request, and the same holds the other way around. When a negotiation is rejected, the function sets only that protocol's flag, so the client still gets one chance to try the other protocol and never more than one. The retry: label sits just before pq_startmsgread(), so execution loops back cleanly to read the next startup packet.
Test Coverage
The commit also adds a new TAP test file, src/test/postmaster/t/004_negotiate.pl, to validate the fix. The test opens a raw socket to the server, sends an SSL request (expecting rejection with 'N'), then a GSS request (also expecting rejection), and finally a second SSL request. It then asserts that the server does not answer with another 'N' rejection, which would mean it had re-entered the negotiation state machine. The server should instead treat the repeated request as an unsupported protocol and close the connection with a FATAL: unsupported frontend protocol 1234.5679 error. A follow-up query confirms that the server stays healthy after the malicious connection attempt.
The fix was backpatched through PostgreSQL 14, which covers all currently supported major versions.
Affected Systems and Versions
The following PostgreSQL versions are affected:
| Major Version | Affected Versions | Fixed Release |
|---|---|---|
| 18 | Versions before 18.4 | 18.4 |
| 17 | Versions before 17.10 | 17.10 |
| 16 | Versions before 16.14 | 16.14 |
| 15 | Versions before 15.18 | 15.18 |
| 14 | Versions before 14.23 | 14.23 |
Vulnerable configurations include:
- Any PostgreSQL instance accepting connections via AF_UNIX sockets (vulnerable regardless of SSL/GSS settings)
- Any PostgreSQL instance accepting TCP connections with both SSL and GSS disabled
Vendor Security History
The PostgreSQL Project has a dedicated Security Team of experienced contributors who manage vulnerability reports and coordinate CVE registrations. The project does not offer bug bounties, but it keeps strict, well-documented policies on what counts as a security vulnerability. For example, the team typically does not consider a denial of service caused by a valid SQL statement from an authenticated user to be a security vulnerability. CVE-2026-6479 needs no authentication. The attack happens during the connection phase, before any authentication takes place, and that is what warranted a formal CVE designation.
The May 2026 release that fixes this vulnerability also includes fixes for 10 other security vulnerabilities and over 60 bugs. The project's practice is to coordinate security fixes into its regular update releases.
Calif.io reported CVE-2026-6479 to the PostgreSQL Project in collaboration with Claude and Anthropic Research.
References
- PostgreSQL CVE-2026-6479 Security Advisory
- NVD Entry for CVE-2026-6479
- PostgreSQL 18.4, 17.10, 16.14, 15.18, and 14.23 Release Announcement
- Commit f7a191f53 (main/18 branch)
- Commit 66cf26b9e (backport variant)
- PostgreSQL 18.4 Release Notes
- PostgreSQL 17.10 Release Notes
- PostgreSQL Security Information
- DB Engines Database Popularity Ranking



