← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-27145 · Disclosed 2026-06-02

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

This is a tollbooth bug where every extra SAN lane makes the same hostname pay again

In Go's crypto/x509, (*x509.Certificate).VerifyHostname used to re-split the same input hostname for every DNS SAN entry it checked. That turns certificate validation into avoidable CPU work when a certificate carries a large DNS SAN list, and the cost lands *before* chain building, so even an otherwise untrusted certificate can trigger it. Supported fixed releases are go1.25.11 and go1.26.4; on supported branches, treat anything earlier than those as affected. Older unsupported branches likely inherited the same code path, but Go's current release stream only documents fixes on 1.25 and 1.26.

There is no vendor CVSS baseline here, so this is ASSESSED AT LOW rather than upgraded or downgraded. The technical trigger is real, but the practical attack surface is narrow: this is mostly a *client-side* outbound TLS problem, the attacker usually needs control of the server certificate on a destination the victim already contacts, and the impact is CPU burn / latency / connection degradation rather than code execution, auth bypass, or data theft.

"ASSESSED AT LOW: this is client-side CPU drag, not a trust bypass, and the attacker usually has to own the TLS endpoint."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Control a TLS endpoint the Go client will talk to

The attacker first needs a path to make a Go client validate a certificate they control. In practice that means running the destination service, steering the victim to an attacker host, or sitting in a position where they can present a certificate during an outbound TLS connection. Tooling is trivial here: any HTTPS/TLS server stack plus a custom certificate is enough.
Conditions required:
  • Victim uses Go crypto/x509 hostname verification, directly or through x509.Verify / TLS client code
  • Attacker can cause the victim to initiate a TLS connection to an attacker-controlled or attacker-influenced endpoint
Where this breaks in practice:
  • This is not a generic internet-facing server bug; it is mostly an outbound client validation path
  • Many enterprise workloads only talk to fixed allowlisted destinations, so random internet attackers cannot usually reach this code path
Detection/coverage: No network scanner will fingerprint this reliably from outside. Reachability is best identified from SBOM/SCA, govulncheck, and inventory of Go client binaries.
STEP 02

Serve a certificate bloated with DNS SAN entries

Using OpenSSL, cfssl, or custom ASN.1 tooling, the attacker presents a certificate containing many DNS SAN entries. The bug is not about trust bypass; it is about making hostname comparison do redundant work over and over on the same host string.
Conditions required:
  • Attacker can present an arbitrary certificate chain to the victim
  • Certificate can carry a large enough SAN set to matter operationally
Where this breaks in practice:
  • Certificate size and handshake practicality cap how absurd this can get
  • Some upstream components or test harnesses may reject malformed or unusually large certificates before they become useful
Detection/coverage: TLS inspection may show abnormally large certificates, but that is not a dependable detection control. Most vuln scanners will miss it because they do not evaluate SAN-count-driven CPU cost.
STEP 03

Trigger repeated hostname splitting before trust is even decided

When the victim validates the certificate hostname, vulnerable Go builds repeatedly call hostname-matching logic that re-processes the same host input for each SAN entry. Because x509.Verify performs hostname validation before chain building, the attacker gets the CPU hit even if the certificate would later fail trust validation.
Conditions required:
  • Victim is on a vulnerable Go toolchain path
  • Hostname verification is actually invoked with VerifyOptions.DNSName or normal TLS client hostname checks
Where this breaks in practice:
  • Strictly valid DNS hostnames are length-limited, so amplification is bounded in the common case
  • Some applications sanitize or clamp hostnames before passing them into Go
Detection/coverage: Application profiling or high-verbosity tracing may show CPU in crypto/x509 during failed handshakes. External IDS/WAF products generally will not surface this as a distinct signature.
STEP 04

Degrade the client, not the trust boundary

The end result is availability drag: elevated CPU, slower TLS setup, and potentially degraded worker throughput if many connections are forced through the expensive path. There is no evidence this becomes certificate forgery, trust bypass, secret disclosure, or code execution.
Conditions required:
  • Victim performs enough outbound handshakes to make the extra CPU meaningful
  • Attacker can repeat the interaction or fan it across many clients
Where this breaks in practice:
  • Single-handshake impact is finite and often just looks like slowness
  • Blast radius is usually limited to the client process or service making the outbound call
Detection/coverage: Watch for spikes in failed outbound TLS handshakes plus CPU concentrated in Go processes. EDR will see process stress, but not the root cause, unless you correlate with Go version and connection logs.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo evidence of active exploitation found in the sources reviewed, and not listed in CISA KEV.
Proof-of-concept availabilityNo standalone public exploit repo was identified; the public technical detail is the Go security issue itself, which is enough for a competent operator to reproduce with standard cert-generation tooling.
EPSSNo published FIRST EPSS score was observed at time of review; this is common for very fresh disclosures.
KEV statusNot in KEV as of 2026-06-03; no KEV add date or due date exists.
Affected componentGo standard library crypto/x509, specifically (*x509.Certificate).VerifyHostname and flows that call x509.Verify with VerifyOptions.DNSName.
Affected versionsOn supported Go branches, treat < go1.25.11 and < go1.26.4 as affected. Older unsupported branches likely contain the same behavior, but Go's current security release notes only document fixed supported lines.
Fixed versionsFixed in go1.25.11 and go1.26.4.
CVSS / vector realityThere is no vendor CVSS or vector. Practically this behaves like a constrained network-triggered availability issue where attacker position and reachability dominate risk more than raw code-path severity.
Scanning / exposure realityShodan/Censys/FOFA are the wrong lens here: this is a linked standard-library bug, not a bannered appliance. You need SBOM/SCA, govulncheck, or go version -m against deployed binaries.
Disclosure / creditPublicly disclosed 2026-06-02. The Go issue credits Jakub Ciolek for reporting.
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to LOW (2.9/10)

The decisive factor is attacker position: this usually requires control of a TLS endpoint the victim's Go client already contacts, which sharply limits reachable population compared with a normal pre-auth server-side bug. The impact is also strictly availability-oriented CPU overhead, with no trust bypass, code execution, or credential exposure in the observed behavior.

HIGH Technical description and fixed supported versions
MEDIUM Real-world severity assessment across mixed enterprise Go deployments
MEDIUM Inference that unsupported older Go branches likely inherit the same code path

Why this verdict

  • Attacker position pushes this down: this is mostly an *outbound client-side* TLS verification bug, so the attacker generally must control the destination service or otherwise steer the victim to an attacker-controlled TLS endpoint.
  • Impact is availability-only: the bug burns CPU during hostname validation; it does not let the attacker forge trust, bypass hostname checks, read data, or run code.
  • Reachable population is narrower than Go's install base: Go is widespread, but only the subset doing vulnerable hostname validation against attacker-influenced endpoints is realistically exposed.
  • A prior-compromise or influence stage is often implied: internal service discovery poisoning, SSRF, redirect abuse, malicious webhooks, or tricking clients into new outbound destinations are common prerequisites in enterprise reality.
  • Modern controls can break the chain early: egress allowlisting, outbound proxy policy, strict destination pinning, and connection timeouts all reduce the exploit path before the stdlib bug matters.
  • Detection is poor but exploit economics are mediocre: scanners will miss it, but attackers also get only a bounded CPU tax rather than a durable foothold.

Why not higher?

This is not an unauthenticated internet-facing server RCE, auth bypass, or direct confidentiality event. The attacker usually needs the victim to connect outward to a hostile TLS endpoint, and even then the practical result is performance degradation rather than a clean security boundary break.

Why not lower?

It is still a real security fix, not just a cosmetic optimization: untrusted certificates can trigger the extra work before chain validation finishes. In environments with many Go clients making attacker-influenced outbound TLS connections, repeated handshakes can turn this into measurable operational pain.

05 · Compensating Control

What to do — in priority order.

  1. Clamp outbound destinations — Enforce egress allowlists or proxy-based destination control so Go clients cannot be pointed at arbitrary TLS endpoints. For a LOW verdict there is no SLA clock here, but put this into normal control hardening and apply it during the next routine policy refresh.
  2. Bound handshake cost — Set conservative dial, TLS handshake, and request timeouts on Go clients and reverse proxies so certificate-validation stalls cannot pile up into worker exhaustion. For LOW, roll this into standard engineering backlog hygiene rather than an emergency change.
  3. Inventory linked Go binaries — Use go version -m or SBOM tooling to identify binaries built with go1.25.10/earlier on the 1.25 line and go1.26.3/earlier on the 1.26 line. This is the fastest way to separate truly exposed assets from noise.
  4. Reject absurd host inputs in app code — If your application accepts user-supplied hostnames before making outbound TLS connections, enforce sane hostname length and label-count checks before those values ever reach Go's verifier. That shrinks the worst-case path even before the toolchain update lands.
What doesn't work
  • Rotating trusted roots or tightening CA stores does not solve the trigger path, because the CPU cost happens before trust chain success matters.
  • Ingress WAF rules usually do not help, because this is commonly an outbound client validation path rather than an inbound web request bug.
  • Relying on vulnerability scanners alone does not work; this is a linked library behavior problem, so unauthenticated network scanning typically cannot see it.
06 · Verification

Crowdsourced verification payload.

Run this on the target host or in CI against the actual deployed Go binaries, not just the build runner. Invoke it as ./check-cve-2026-27145.sh /opt/app/bin/service or with multiple binaries; if you pass no arguments it falls back to the locally installed go toolchain. No root is required, but you need read access to the binaries and go in PATH if you want the fallback check.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check-cve-2026-27145.sh
# Determine likely exposure to CVE-2026-27145 in Go binaries/toolchains.
# Exit codes:
#   0 = PATCHED
#   1 = VULNERABLE
#   2 = UNKNOWN / usage / cannot determine

set -u

status=0
saw_unknown=0

extract_go_version() {
  local target="$1"
  local out ver
  out=$(go version -m "$target" 2>/dev/null | head -n1) || return 1
  ver=$(printf '%s\n' "$out" | awk '{print $2}')
  [ -n "$ver" ] || return 1
  printf '%s\n' "$ver"
}

extract_local_toolchain() {
  local out ver
  out=$(go version 2>/dev/null) || return 1
  ver=$(printf '%s\n' "$out" | awk '{print $3}')
  [ -n "$ver" ] || return 1
  printf '%s\n' "$ver"
}

classify_version() {
  local ver="$1"
  local clean major minor patch rest

  clean="${ver#go}"
  clean="${clean%%[- ]*}"

  case "$clean" in
    devel*|tip*)
      echo "UNKNOWN"
      return 0
      ;;
  esac

  IFS='.' read -r major minor patch rest <<EOF
$clean
EOF

  if ! [[ "$major" =~ ^[0-9]+$ && "$minor" =~ ^[0-9]+$ ]]; then
    echo "UNKNOWN"
    return 0
  fi

  if ! [[ "${patch:-}" =~ ^[0-9]+$ ]]; then
    patch=0
  fi

  # Supported fixed releases documented by Go:
  #   1.25.11+
  #   1.26.4+
  # Assume newer branches carry the fix.
  if (( major > 1 )); then
    echo "PATCHED"
    return 0
  fi

  if (( major < 1 )); then
    echo "UNKNOWN"
    return 0
  fi

  if (( minor >= 27 )); then
    echo "PATCHED"
    return 0
  fi

  if (( minor == 26 )); then
    if (( patch >= 4 )); then
      echo "PATCHED"
    else
      echo "VULNERABLE"
    fi
    return 0
  fi

  if (( minor == 25 )); then
    if (( patch >= 11 )); then
      echo "PATCHED"
    else
      echo "VULNERABLE"
    fi
    return 0
  fi

  # Older/EOL lines are not covered by the current supported-branch advisory.
  # They may still contain the bug, but we avoid guessing.
  echo "UNKNOWN"
}

report_one() {
  local label="$1"
  local ver="$2"
  local verdict
  verdict=$(classify_version "$ver")
  printf '%s: %s (%s)\n' "$label" "$verdict" "$ver"

  case "$verdict" in
    VULNERABLE)
      status=1
      ;;
    UNKNOWN)
      saw_unknown=1
      ;;
  esac
}

if [ "$#" -gt 0 ]; then
  if ! command -v go >/dev/null 2>&1; then
    echo "UNKNOWN: 'go' command not found; cannot inspect binaries with go version -m"
    exit 2
  fi

  for bin in "$@"; do
    if [ ! -r "$bin" ]; then
      echo "$bin: UNKNOWN (file not readable)"
      saw_unknown=1
      continue
    fi

    ver=$(extract_go_version "$bin")
    if [ -z "${ver:-}" ]; then
      echo "$bin: UNKNOWN (not a Go binary with embedded build info, or stripped beyond inspection)"
      saw_unknown=1
      continue
    fi

    report_one "$bin" "$ver"
  done
else
  ver=$(extract_local_toolchain)
  if [ -z "${ver:-}" ]; then
    echo "UNKNOWN: local Go toolchain not found"
    exit 2
  fi
  report_one "local-go-toolchain" "$ver"
fi

if [ "$status" -eq 1 ]; then
  exit 1
fi

if [ "$saw_unknown" -eq 1 ]; then
  exit 2
fi

exit 0
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, do not open an emergency change window for this one unless you have Go clients that routinely connect to attacker-influenced TLS endpoints. Inventory linked Go binaries, queue upgrades to go1.25.11 or go1.26.4 in the next normal toolchain refresh, and document any outbound-facing exceptions that accept user-controlled hostnames. For a LOW verdict there is noisgate mitigation SLA and noisgate remediation SLA is no SLA (treat as backlog hygiene); this belongs in ordinary patch hygiene, not the front of the fire line.

Sources

  1. Go release history
  2. Go issue #79694 - root security issue
  3. Go issue #79701 - 1.26 backport
  4. Go 1.25.11 cherry-pick issue query
  5. Go 1.26.4 cherry-pick issue query
  6. Go `crypto/x509` package docs
  7. CISA Known Exploited Vulnerabilities Catalog
  8. FIRST EPSS data documentation
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.