ZeroPath at Black Hat USA 2026

PostgreSQL CVE-2026-6479: Brief Summary of Unauthenticated DoS via SSL/GSS Negotiation Recursion

A brief summary of CVE-2026-6479, a high severity denial of service vulnerability in PostgreSQL caused by uncontrolled recursion during SSL and GSS negotiation. Includes patch analysis and affected version details.

CVE Analysis

8 min read

ZeroPath CVE Analysis
ZeroPath CVE Analysis

2026-05-14

PostgreSQL CVE-2026-6479: Brief Summary of Unauthenticated DoS via SSL/GSS Negotiation Recursion
Experimental AI-Generated Content

This CVE analysis is an experimental publication that is completely AI-generated. The content may contain errors or inaccuracies and is subject to change as more information becomes available. We are continuously refining our process.

If you have feedback, questions, or notice any errors, please reach out to us.

[email protected]

Introduction

A single unauthenticated connection to a PostgreSQL server can now crash a backend process through nothing more than a carefully sequenced series of SSL and GSS negotiation messages. CVE-2026-6479, disclosed on May 14, 2026, exposes a flaw in how PostgreSQL handles encryption negotiation during the connection startup phase, allowing sustained denial of service with a CVSS 3.1 base score of 7.5.

PostgreSQL ranks as the fourth most popular database management system globally, with a DB Engines score of 682.68 as of May 2026. That ubiquity means this vulnerability has a broad blast radius across cloud infrastructure, SaaS platforms, and enterprise deployments alike.

Technical Information

Root Cause: Uncontrolled Recursion in ProcessStartupPacket()

The vulnerability is classified under CWE-674 (Uncontrolled Recursion) and lives in the ProcessStartupPacket() function, which is responsible for handling 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 core problem is architectural: when the server received an SSL or GSS negotiation request, ProcessStartupPacket() handled it by calling itself recursively. Each negotiation attempt pushed a new stack frame onto the call stack. Critically, 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 regardless. By sending these requests indefinitely, the attacker could grow the call stack without bound until it overflowed, crashing the connected backend process.

Attack Flow

The exploitation sequence is straightforward:

  1. The attacker opens a raw socket connection to the PostgreSQL server (either AF_UNIX or TCP).
  2. The attacker sends an SSL negotiation request. The server rejects it (responding with 'N') and recurses into ProcessStartupPacket().
  3. The attacker then sends a GSS negotiation request. The server rejects it and recurses again.
  4. The attacker repeats steps 2 and 3, alternating between SSL and GSS requests.
  5. Each iteration adds another stack frame. After enough iterations, the call stack overflows and the backend process crashes.

Attack Surface Depends on Configuration

The exploitability over the network depends on the server's encryption configuration:

Connection TypeSSL and GSS StatusVulnerability Status
AF_UNIX socketAny configurationVulnerable to denial of service
TCP socketBoth SSL and GSS disabledVulnerable to denial of service

Local socket access (AF_UNIX) is always a risk regardless of encryption settings. Network based attacks over TCP are specifically enabled when administrators have disabled both SSL and GSS protocols, because in that configuration both negotiation types are rejected but still processed 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. The patch was authored by Michael Paquier and committed by Noah Misch (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 elegant in its simplicity: 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. This keeps the stack depth constant regardless of how many negotiation messages a client sends.

Here is the core change in src/backend/tcop/backend_startup.c (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;

An identical transformation was applied 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;

There is an important semantic nuance here: when a negotiation succeeds (e.g., SSLok == 'S'), the function also marks the other protocol as done. This makes sense because once SSL encryption has been successfully established, there is no reason to entertain a subsequent GSS encryption request (and vice versa). When a negotiation is rejected, only the specific protocol flag is set, still allowing the client one chance to try the other protocol, but never more than that. The retry: label sits just before pq_startmsgread(), so execution loops back cleanly to read the next startup packet.

Test Coverage

The commit also introduces a new TAP test file, src/test/postmaster/t/004_negotiate.pl, that validates this 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 sends a second SSL request. The test asserts that the server does not respond with another 'N' rejection (which would indicate it re entered the negotiation state machine) and instead treats the repeated request as an unsupported protocol, closing the connection with a FATAL: unsupported frontend protocol 1234.5679 error. A follow up query confirms the server remains healthy after handling the malicious connection attempt.

The fix was backpatched through PostgreSQL 14, covering all currently supported major versions.

Affected Systems and Versions

The following PostgreSQL versions are affected:

Major VersionAffected VersionsFixed Release
18Versions before 18.418.4
17Versions before 17.1017.10
16Versions before 16.1416.14
15Versions before 15.1815.18
14Versions before 14.2314.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 operates a dedicated Security Team comprising experienced contributors who manage vulnerability reports and coordinate CVE registrations. While the project does not offer bug bounties, it maintains strict and well documented policies on what constitutes a security vulnerability. Notably, the team typically does not consider a denial of service from an authenticated valid SQL statement to be a security vulnerability. The unauthenticated nature of CVE-2026-6479, occurring during the connection phase before any authentication takes place, is what warranted a formal CVE designation.

The May 2026 release that addresses this vulnerability also bundles fixes for 10 other security vulnerabilities and over 60 bugs, reflecting the project's practice of coordinating security fixes into regular update releases.

CVE-2026-6479 was reported to the PostgreSQL Project by Calif.io in collaboration with Claude and Anthropic Research.

References

Detect & fix
what others miss

Works with
  • GitHub
  • GitLab
  • Bitbucket
  • Azure DevOps Services
  • Jira
  • Linear
  • Slack
  • Security Compass
Security magnifying glass visualization