CVE-2026-26994 Overview
CVE-2026-26994 is a TLS downgrade protection bypass vulnerability affecting uTLS, a fork of Go's crypto/tls library designed to customize ClientHello messages for fingerprinting resistance. The vulnerability exists because uTLS versions 1.6.7 and below failed to implement the TLS 1.3 downgrade protection mechanism specified in RFC 8446 Section 4.1.3 when using a uTLS ClientHello spec.
This flaw allows an active network adversary to force TLS 1.3 connections initiated by a uTLS client to downgrade to TLS 1.2 or lower by manipulating the ClientHello message to exclude the SupportedVersions extension. Because uTLS did not verify the downgrade canary in the ServerHello random field, clients would accept the downgraded connection without detecting the man-in-the-middle attack.
Critical Impact
Active network attackers can downgrade TLS 1.3 connections to weaker protocol versions, enabling man-in-the-middle attacks and fingerprinting of uTLS connections.
Affected Products
- refraction-networking utls versions 1.6.7 and below
- Go applications using uTLS for TLS fingerprint resistance
- Privacy and circumvention tools built on the uTLS library
Discovery Timeline
- 2026-02-20 - CVE-2026-26994 published to NVD
- 2026-02-20 - Last updated in NVD database
Technical Details for CVE-2026-26994
Vulnerability Analysis
The vulnerability stems from an incomplete implementation of the TLS 1.3 specification in the uTLS library. RFC 8446 Section 4.1.3 mandates that TLS 1.3-capable clients must verify a special "downgrade canary" value embedded in the ServerHello random field when negotiating a lower protocol version. This canary mechanism allows clients to detect when an active attacker has modified the handshake to force a protocol downgrade.
In affected versions of uTLS, this verification was entirely absent from the handshake client implementation (u_handshake_client.go). When a server supporting TLS 1.3 is forced by an attacker to respond with a TLS 1.2 ServerHello, it includes specific sentinel values in the last 8 bytes of the random field to signal the downgrade. Without checking these canaries, the uTLS client proceeds with the weakened connection, unaware that the handshake has been tampered with.
Root Cause
The root cause is the missing implementation of downgrade canary validation in the uTLS handshake client code. While the standard Go crypto/tls library properly checks for the downgradeCanaryTLS12 and downgradeCanaryTLS11 sentinel values in the ServerHello random field, this critical security check was not ported to uTLS when customizing the ClientHello spec handling. This oversight violated CWE-693 (Protection Mechanism Failure), leaving clients vulnerable to protocol downgrade attacks.
Attack Vector
An active network adversary positioned between the uTLS client and server can exploit this vulnerability through the following attack flow:
- The attacker intercepts the ClientHello message from the uTLS client
- The attacker modifies or strips the SupportedVersions extension to exclude TLS 1.3
- The server, seeing no TLS 1.3 support, responds with a TLS 1.2 ServerHello containing the downgrade canary
- The uTLS client ignores the canary and accepts the TLS 1.2 connection
- The attacker can now leverage weaker TLS 1.2 security properties or fingerprint the connection
// If we are negotiating a protocol version that's lower than what we
// support, check for the server downgrade canaries.
// See RFC 8446, Section 4.1.3.
maxVers := c.config.maxSupportedVersion(roleClient)
tls12Downgrade := string(serverHello.random[24:]) == downgradeCanaryTLS12
tls11Downgrade := string(serverHello.random[24:]) == downgradeCanaryTLS11
if maxVers == VersionTLS13 && c.vers <= VersionTLS12 && (tls12Downgrade || tls11Downgrade) ||
maxVers == VersionTLS12 && c.vers <= VersionTLS11 && tls11Downgrade {
c.sendAlert(alertIllegalParameter)
return errors.New("tls: downgrade attempt detected, possibly due to a MitM attack or a broken middlebox")
}
Source: GitHub Commit Update
Detection Methods for CVE-2026-26994
Indicators of Compromise
- TLS connections unexpectedly negotiating TLS 1.2 when TLS 1.3 is expected and supported
- Unusual modification patterns in ClientHello messages indicating tampering with SupportedVersions extensions
- Network traffic analysis showing protocol version mismatches between client capabilities and negotiated versions
Detection Strategies
- Implement network monitoring to detect TLS version downgrade patterns where clients supporting TLS 1.3 negotiate TLS 1.2
- Deploy dependency scanning tools to identify applications using vulnerable uTLS versions (< 1.7.0)
- Enable TLS handshake logging to capture negotiated protocol versions and compare against expected client capabilities
- Use software composition analysis (SCA) tools to audit Go dependencies for the vulnerable refraction-networking/utls package
Monitoring Recommendations
- Monitor for tls: downgrade attempt detected error messages after upgrading to version 1.7.0, which may indicate active attack attempts
- Track TLS protocol version distribution in network traffic to identify anomalous downgrade patterns
- Implement alerts for applications using outdated uTLS library versions in your software inventory
How to Mitigate CVE-2026-26994
Immediate Actions Required
- Upgrade uTLS to version 1.7.0 or later immediately to enable downgrade protection
- Audit all applications and dependencies that use the refraction-networking/utls Go module
- Review Go module dependencies using go list -m all | grep utls to identify affected projects
- Rebuild and redeploy applications using the patched uTLS library
Patch Information
The vulnerability has been fixed in uTLS version 1.7.0. The patch adds proper verification of the TLS downgrade canary values in the ServerHello random field, as specified in RFC 8446 Section 4.1.3. The fix checks for both downgradeCanaryTLS12 and downgradeCanaryTLS11 sentinel values and terminates the connection with an alertIllegalParameter if a downgrade attempt is detected.
For complete patch details, see the GitHub Security Advisory, GitHub Pull Request, and GitHub Commit Update.
Workarounds
- If immediate upgrade is not possible, consider enforcing TLS 1.3-only connections at the network level to prevent downgrade attacks
- Deploy network security controls that detect and block ClientHello tampering attempts
- Use alternative TLS libraries with proper downgrade protection if uTLS cannot be updated in the short term
# Update uTLS dependency to patched version
go get github.com/refraction-networking/utls@v1.7.0
go mod tidy
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


