CVE-2026-54291: pgjdbc Fix for Silent Channel-Binding Downgrade
Summary
The patch addresses a fail-open path in pgjdbc where connections configured with channelBinding=require could proceed with non-channel-bound SCRAM-SHA-256 when tls-server-end-point channel binding data could not be derived from the server certificate. The fix adds explicit rejection when the negotiated SCRAM mechanism is not a -PLUS variant under REQUIRE, and when certificate-derived channel binding data is unavailable under REQUIRE. The added regression tests cover unsupported certificate signature algorithms and non-SSL connections.
Analysis
Vulnerability
CVE-2026-54291 describes a silent authentication downgrade in pgjdbc affecting configurations that set channelBinding=require. According to the advisory context in MITRE and the code change in the upstream commit, the driver could fall back from channel-bound SCRAM to plain SCRAM-SHA-256 when the presented server certificate used a signature algorithm for which tls-server-end-point channel binding data could not be derived, such as Ed25519.
This is a fail-open behavior. Under channelBinding=require, inability to compute channel binding data should terminate authentication, because the security property being requested is authenticated binding of the SCRAM exchange to the TLS channel. If the client instead accepts a non-PLUS mechanism, a man-in-the-middle can strip the stronger mode and defeat the intended protection.
return TlsServerEndpoint.getChannelBindingData(cert);The vulnerable behavior shown in the patch summary is that channel binding data extraction was treated as a simple helper return path, without enforcing that REQUIRE must reject empty or unusable binding material.
Patch
The patch in commit 77df98e4e66c12936ded3478a0954f6f580bad99 adds two explicit enforcement points.
First, after SCRAM negotiation resolves, the code now rejects any mechanism that is not a -PLUS mechanism when channelBinding == REQUIRE. This closes the downgrade path even if negotiation otherwise selected plain SCRAM-SHA-256.
Second, when extracting tls-server-end-point data from the peer certificate, the code now checks for an empty result. If no channel binding hash can be derived and the mode is REQUIRE, the driver throws PSQLException with PSQLState.CONNECTION_REJECTED and includes the certificate signature algorithm in the error message.
if (channelBinding == ChannelBinding.REQUIRE && !client.getScramMechanism().isPlus()) {
throw new PSQLException(
GT.tr("Channel Binding is required, but the negotiated SCRAM mechanism \"{0}\" "
+ "does not use channel binding.", client.getScramMechanism().getName()),
PSQLState.CONNECTION_REJECTED);
}
byte[] cbindData = TlsServerEndpoint.getChannelBindingData(cert);
if (cbindData.length > 0) {
return cbindData;
}
if (channelBinding == ChannelBinding.REQUIRE) {
throw new PSQLException(
GT.tr("Channel Binding is required, but the server certificate signature "
+ "algorithm \"{0}\" does not support tls-server-end-point channel "
+ "binding (RFC 5929). Use a server certificate signed with RSA or ECDSA.",
cert.getSigAlgName()),
PSQLState.CONNECTION_REJECTED);
}The accompanying regression tests validate two important cases from the same commit: rejection when the certificate algorithm is unsupported for channel binding derivation, and rejection when channelBinding=require is used without SSL.
Review
Pros
The patch directly addresses the root security invariant: channelBinding=require must not degrade to a non-channel-bound authentication path. The new isPlus() enforcement is strong because it validates the post-negotiation outcome rather than assuming earlier logic selected a compliant mechanism.
The certificate-path check is also well targeted. An empty result from TlsServerEndpoint.getChannelBindingData(cert) is now treated as a hard failure under REQUIRE, which is the correct fail-closed behavior for unsupported signature algorithms such as Ed25519 in the tls-server-end-point context described by the patch comments.
The tests are meaningful and source-grounded. They cover unsupported certificate signature algorithms and non-SSL transport, both of which are realistic preconditions for accidental downgrade or misconfiguration. The assertion that the exception message contains the offending algorithm improves diagnosability for operators.
Cons
The patch is narrowly scoped to enforcement and does not expand protocol capability. Environments using certificates whose signature algorithms do not map to tls-server-end-point remain incompatible with channelBinding=require, so the operational burden shifts to certificate selection or deployment changes.
The remediation message recommends RSA or ECDSA certificates, which is practical but somewhat policy-opinionated. If future support for alternative channel binding strategies or broader algorithm handling is added, this guidance may become too specific.
Based on the provided diff, the review cannot confirm whether all call paths that can influence SCRAM mechanism selection are covered by equivalent invariant checks elsewhere. However, the added post-negotiation isPlus() guard substantially reduces that concern.
Verdict
Root-cause.
This patch fixes the underlying fail-open condition rather than masking symptoms. It enforces the semantic contract of channelBinding=require at two critical boundaries: negotiated mechanism selection and certificate-derived channel binding material availability. That is the correct security model for preventing silent downgrade. The regression coverage in the upstream commit supports confidence that the vulnerable behavior described in NVD is specifically addressed by the implementation in the patch.
Recommended Labs
Try this vulnerability pattern yourself with hands-on labs.
- OAuth.java
Best available Java hands-on defensive lab aligned to the CVE’s authentication-integrity theme. While it is not a PostgreSQL/TLS channel-binding-specific lab, it focuses on fixing replay/authentication weaknesses and helps build the mindset needed to prevent silent security downgrades in auth flows.
- Bad token.java
Useful for practicing defensive fixes around token misuse and broken authentication assumptions. This is relevant because CVE-2026-54291 is fundamentally an authentication-protection downgrade issue where a stronger guarantee is silently weakened.
- Confusable.java
Most relevant available lab for spoofing/MITM-adjacent thinking in Java. It is not about TLS channel binding directly, but it does train developers to detect and defend against trust confusion and identity spoofing issues, which are conceptually close to the downgrade/MITM risk described in this CVE.