← Back to Feed CACHED · 2026-09-20 05:56:12 · CACHE_KEY CVE-2026-56862
CVE-2026-56862 · CWE-770 · Disclosed 2026-08-13

Handshake messages

ASSESSED — NOISGATE
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

Leaving the faucet running so the water heater never stops burning gas

CVE-2026-56862 is a denial-of-service vulnerability in Go's standard library crypto/tls package. In TLS 1.3, a KeyUpdate message instructs the peer to derive a fresh set of traffic keys — an intentionally expensive cryptographic operation. Go's implementation treated every KeyUpdate as "state-advancing" and imposed no rate limit on how many a remote peer could send, even after the handshake was already complete. A malicious client can open a single TLS 1.3 connection and flood it with KeyUpdate messages, pinning a server goroutine to continuous HKDF-Expand-Label derivations and consuming CPU indefinitely. Affected versions span every supported Go release branch: anything before go1.25.13, go1.26.0 through go1.26.5, and go1.27.0 through go1.27.0-rc.2. The fix (go1.25.13, go1.26.6, go1.27.0-rc.3) bounds how often rekeying is honored.

The vendor's CVSS 7.5 HIGH rating is technically correct on paper — the vector is unauthenticated, network-reachable, low-complexity, and availability-impacting. But in practice it overstates the risk for most enterprise fleets. First, this is availability-only: no confidentiality leak, no integrity compromise, no code execution. Second, the dominant deployment pattern for Go services in production puts them behind a TLS-terminating reverse proxy (nginx, Envoy, HAProxy, AWS ALB/NLB, GCP Cloud Load Balancer), meaning the Go process never sees raw TLS records and is completely shielded. Third, the DoS is connection-scoped — an attacker must maintain active connections to sustain the CPU burn, and standard connection-timeout and concurrency-limit configurations bound the blast radius. Ubuntu's security team independently downgraded this to Medium priority. noisgate agrees: for most enterprises, this is a MEDIUM.

"DoS-only flaw in Go crypto/tls; most prod Go servers sit behind TLS-terminating proxies."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Identify a Go TLS 1.3 endpoint

The attacker scans for services that negotiate TLS 1.3 and are served directly by a Go binary (not fronted by a TLS-terminating proxy). Tools like testssl.sh, nmap --script ssl-enum-ciphers, or custom Go clients can fingerprint the TLS implementation. Services directly exposed include self-hosted Go APIs, Kubernetes API servers without an external LB, and internal microservices communicating via mTLS.
Conditions required:
  • Network reachability to the TLS endpoint (external or internal)
  • Target must negotiate TLS 1.3 (default in Go ≥1.13)
Where this breaks in practice:
  • Most production Go services sit behind nginx, Envoy, or cloud LBs that terminate TLS before the Go process
  • Internal-only services require the attacker to already have network access inside the perimeter
Detection/coverage: TLS fingerprinting with JA3/JA4 can identify Go's crypto/tls stack but is not widely deployed for this purpose.
STEP 02

Establish a TLS 1.3 connection

The attacker completes a standard TLS 1.3 handshake. No authentication is required — the vulnerability is exploitable by any client that can complete the handshake. A simple Go client or a modified OpenSSL s_client suffices. The connection enters the application-data phase normally.
Conditions required:
  • Ability to complete a TLS 1.3 handshake (no client cert required unless server enforces mTLS)
Where this breaks in practice:
  • If the server enforces mutual TLS (mTLS), the attacker needs a valid client certificate, which significantly narrows the attacker population
  • Connection rate limiting or SYN cookies at the network edge may slow establishment
Detection/coverage: Standard connection logging captures new TLS sessions. Anomalous connection volume from a single source is detectable by NGFW or SIEM correlation.
STEP 03

Flood KeyUpdate messages

After the handshake completes, the attacker sends a rapid stream of TLS KeyUpdate messages (record type 0x16, handshake type 24). Each message is only 5 bytes of TLS record payload. Because Go's crypto/tls treats these as state-advancing, they bypass the non-advancing record limit that would otherwise throttle junk records. The server dutifully derives a new set of traffic keys for every single message.
Conditions required:
  • Active TLS 1.3 connection to the target
  • No intermediary that strips or filters post-handshake TLS records
Where this breaks in practice:
  • A TLS-terminating reverse proxy absorbs the KeyUpdate messages — the Go backend never sees them
  • Connection idle timeouts (typically 60–120s) limit the duration of any single attack connection
  • Per-connection concurrency limits bound how many goroutines an attacker can pin simultaneously
Detection/coverage: Deep packet inspection at the TLS record layer could detect anomalous KeyUpdate frequency, but most enterprise IDS/IPS do not inspect post-handshake TLS 1.3 records. Application-level CPU monitoring (Go pprof, runtime metrics) would show elevated crypto/tls CPU time.
STEP 04

Sustained CPU exhaustion

Each KeyUpdate triggers HKDF-Expand-Label key derivation, which is computationally expensive relative to a 5-byte trigger message. With hundreds of connections each sending thousands of KeyUpdate messages per second, the attacker can saturate the server's CPU cores. The effect persists only while the attacker maintains the connections — this is not an amplification attack and there is no persistent damage. Service resumes once the malicious connections are dropped.
Conditions required:
  • Sufficient bandwidth to maintain multiple concurrent TLS connections
  • Target server has no connection-level rate limiting
Where this breaks in practice:
  • Auto-scaling infrastructure (Kubernetes HPA, cloud auto-scale groups) can absorb transient CPU spikes
  • Goroutine and connection limits (http.Server.MaxConns, net.Listener wrappers) cap the blast radius
  • Watchdog processes and health checks restart unresponsive pods/services, limiting downtime window
Detection/coverage: CPU utilization spikes on Go processes are trivially visible in Prometheus/Grafana, Datadog, or any APM stack. Alert on sustained >90% CPU on Go TLS-serving processes.
03 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNo known exploitation. Not listed in CISA KEV. No threat campaigns or APT usage reported as of 2026-09-20.
Proof-of-conceptNo public PoC repository found. However, the attack is trivially constructable — a Go client sending KeyUpdate in a loop requires ~20 lines of code. No weaponized tooling (Metasploit, Nuclei template) identified.
EPSS0.57% probability of exploitation in the next 30 days (44.9th percentile). Below the typical action threshold of 10%.
KEV statusNot listed in CISA Known Exploited Vulnerabilities catalog.
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H — Unauthenticated network DoS, no scope change, availability-only impact. No confidentiality or integrity impact.
Affected versionsGo standard library crypto/tls: < go1.25.13, go1.26.0 – go1.26.5, go1.27.0 – go1.27.0-rc.2. All Go binaries compiled with these toolchains inherit the flaw.
Fixed versionsgo1.25.13, go1.26.6, go1.27.0-rc.3 and later. Distro backports: Ubuntu and Red Hat packages pending evaluation (RHSA-2026:67975 issued). Downstream projects (KrakenD CE 2.13.9, EE 2.13.7) shipping rebuilt binaries.
Scanning / exposureNo GreyNoise or Shodan tags specific to this CVE. Go TLS endpoints are not trivially distinguishable from other TLS stacks via passive scanning. JA3/JA4 fingerprinting can identify Go's crypto/tls but requires active probing.
Disclosure date2026-08-13 (coordinated disclosure via Go security process, golang/go#80528).
CreditQi Deng of Aurascape.ai. Related sibling CVE: CVE-2026-32283 (TLS 1.3 KeyUpdate deadlock — separate fix, same attack surface).
04 · The Call

Final Verdict
DOWNGRADED to MEDIUM (5.5/10)

Why this verdict

  • Availability-only impact ceiling: The CVSS vector confirms C:N/I:N — no data exfiltration, no code execution, no privilege escalation. The worst outcome is temporary service unavailability, which is a lower-consequence outcome than the HIGH label implies.
  • TLS-terminating proxy pattern dominates production: The vast majority of Go services in enterprise environments (Kubernetes pods, cloud-hosted APIs, microservices behind service meshes like Istio/Linkerd) sit behind reverse proxies or load balancers that terminate TLS. The Go process never receives raw TLS records, making it immune. Conservative estimate: >70% of Go TLS services in enterprise fleets are shielded this way.
  • Connection-scoped, non-persistent DoS: The attacker must maintain active connections to sustain CPU burn. There is no amplification, no persistence, and no lasting damage. Dropping the connections immediately restores service. Standard connection timeouts (60–120s) and concurrency limits bound the blast radius without any patching.
  • Low exploitation probability: EPSS 0.57% (44.9th percentile), no KEV listing, no known campaigns, no public weaponized PoC. The attack requires a custom TLS client — it won't be swept up in opportunistic scanning.
  • Role multiplier: Go's crypto/tls is used in high-value infrastructure: Kubernetes API server, etcd, Vault, Consul, Docker registry, Prometheus. The chain succeeds if these components terminate TLS directly (some Kubernetes API servers do). However, even in the worst case — DoS of a Kubernetes API server — the outcome is *temporary cluster management unavailability*, not domain takeover, fleet compromise, or data exfiltration. This does not meet the HIGH floor threshold of 'domain takeover / fleet compromise / mass data egress / supply-chain pivot.' For etcd and Vault: same analysis — availability disruption, not compromise. The floor does not apply.
  • Ubuntu independent assessment confirms: Ubuntu's security team independently rated this Medium priority, aligning with our friction analysis rather than the vendor's CVSS label.

Why not higher?

The vendor's HIGH (7.5) would be justified if the majority of Go TLS services were directly exposed to untrusted clients without intermediary TLS termination. In practice, the enterprise deployment pattern (reverse proxy → Go backend) shields most targets. The impact ceiling is availability-only with no path to compromise, which caps the real-world severity below HIGH even for directly-exposed instances.

Why not lower?

Despite the heavy friction, the attack vector is genuinely unauthenticated and low-complexity against directly-exposed Go TLS services. Some Kubernetes API servers, internal mTLS microservices, and standalone Go web servers *do* terminate TLS natively. A motivated attacker with internal network access could selectively DoS critical Go infrastructure components. The breadth of the Go ecosystem means millions of binaries are theoretically affected, and recompilation is the only true fix — there is no runtime configuration toggle to disable TLS 1.3 KeyUpdate processing.

05 · Compensating Control

What to do — in priority order.

  1. Place Go services behind a TLS-terminating reverse proxy — If the Go process doesn't handle raw TLS, this CVE is completely neutralized. Deploy nginx, Envoy, HAProxy, or a cloud LB in front of any directly-exposed Go TLS endpoint. This is the single most effective control and should be prioritized as a noisgate remediation SLA item within the 365-day MEDIUM window, or immediately for any internet-facing Go TLS services.
  2. Set connection timeouts and concurrency limits — Configure http.Server.ReadTimeout, WriteTimeout, and IdleTimeout (e.g., 60s each) and use http.Server.MaxHeaderBytes or golang.org/x/net/netutil.LimitListener to cap concurrent connections. This bounds the CPU burn duration and attacker resource commitment. Deploy within the remediation window.
  3. Upgrade Go toolchain and rebuild affected binaries — Update to go1.25.13+, go1.26.6+, or go1.27.0-rc.3+ and recompile all affected services. This is the definitive fix. For the MEDIUM verdict, the noisgate remediation SLA gives 365 days, but prioritize internet-facing and high-value services (Kubernetes components, API gateways) within 90 days.
  4. Monitor Go process CPU utilization — Alert on sustained CPU spikes (>90% for >60s) on Go TLS-serving processes via Prometheus, Datadog, or your APM stack. This provides detection-in-depth while patching rolls out. Configure immediately as an observability hygiene item.
  5. Enforce mTLS where feasible — Requiring client certificates eliminates unauthenticated attackers from the threat model. This is already standard in service meshes (Istio, Linkerd) and Kubernetes internal communication. Verify enforcement on any Go service that terminates TLS directly.
What doesn't work
  • WAF rules — Web Application Firewalls operate at the HTTP layer (L7) and cannot inspect or filter TLS 1.3 post-handshake records, which are processed before HTTP parsing begins.
  • Disabling TLS 1.3 via Go configuration — While tls.Config.MaxVersion = tls.VersionTLS12 would technically prevent TLS 1.3 negotiation, this trades a DoS vulnerability for a cryptographic downgrade and is not recommended as a compensating control.
  • IP-based rate limiting alone — The attack requires only a small number of connections; IP rate limiting at the connection level won't prevent a slow-and-low variant with a handful of persistent connections from a single source.
06 · Verification

Crowdsourced verification payload.

Run this script on any host where Go binaries are deployed or the Go toolchain is installed. Execute as any user with read access to the target binaries: bash check_cve_2026_56862.sh [/path/to/go-binary]. If no argument is given, it checks the system Go toolchain version. No elevated privileges required.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cve_2026_56862.sh — Detect Go crypto/tls KeyUpdate DoS (CVE-2026-56862)
# Usage: bash check_cve_2026_56862.sh [/path/to/go-binary]
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN

set -euo pipefail

parse_go_version() {
  local raw="$1"
  # Extract version like go1.25.13 or go1.26.6
  local ver
  ver=$(echo "$raw" | grep -oP 'go1\.\d+\.\d+' | head -1)
  if [[ -z "$ver" ]]; then
    ver=$(echo "$raw" | grep -oP 'go1\.\d+' | head -1)
    if [[ -n "$ver" ]]; then ver="${ver}.0"; fi
  fi
  echo "$ver"
}

check_version() {
  local ver="$1"
  local major minor patch
  major=$(echo "$ver" | sed 's/go//' | cut -d. -f1)
  minor=$(echo "$ver" | cut -d. -f2)
  patch=$(echo "$ver" | cut -d. -f3)
  patch=${patch:-0}

  # go1.25.x: fixed in 1.25.13
  if [[ "$minor" -le 25 ]]; then
    if [[ "$minor" -lt 25 ]]; then
      echo "VULNERABLE"
    elif [[ "$patch" -lt 13 ]]; then
      echo "VULNERABLE"
    else
      echo "PATCHED"
    fi
  # go1.26.x: fixed in 1.26.6
  elif [[ "$minor" -eq 26 ]]; then
    if [[ "$patch" -lt 6 ]]; then
      echo "VULNERABLE"
    else
      echo "PATCHED"
    fi
  # go1.27.x: fixed in 1.27.0-rc.3 (treat any 1.27.0+ release as patched for simplicity)
  elif [[ "$minor" -ge 27 ]]; then
    echo "PATCHED"
  else
    echo "UNKNOWN"
  fi
}

if [[ $# -ge 1 ]]; then
  TARGET="$1"
  if [[ ! -f "$TARGET" ]]; then
    echo "UNKNOWN — file not found: $TARGET"
    exit 2
  fi
  RAW=$(go version "$TARGET" 2>/dev/null || true)
  if [[ -z "$RAW" ]]; then
    echo "UNKNOWN — could not determine Go version for $TARGET (not a Go binary or 'go' not in PATH)"
    exit 2
  fi
else
  RAW=$(go version 2>/dev/null || true)
  if [[ -z "$RAW" ]]; then
    echo "UNKNOWN — Go toolchain not found in PATH"
    exit 2
  fi
fi

VER=$(parse_go_version "$RAW")
if [[ -z "$VER" ]]; then
  echo "UNKNOWN — could not parse Go version from: $RAW"
  exit 2
fi

RESULT=$(check_version "$VER")
echo "$RESULT — $RAW (parsed: $VER)"

case "$RESULT" in
  PATCHED)    exit 0 ;;
  VULNERABLE) exit 1 ;;
  *)          exit 2 ;;
esac
07 · Sources

Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.