← Back to Feed CACHED · 2026-09-20 06:03:39 · CACHE_KEY CVE-2026-75595
CVE-2026-75595 · CWE-754 · Disclosed 2026-08-19

Netty is an asynchronous

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

The bouncer checks IDs at the VIP door, but a garbled name makes him wave you through the main entrance instead

CVE-2026-75595 is an authentication bypass in Netty's SslClientHelloHandler#decode. An off-by-five-byte bounds-check error means the code validates 4 bytes of buffer space but then reads 9 (5-byte TLS record header + 4-byte handshake header). When an attacker sends a crafted ClientHello whose handshake header spans TLS records — with a first-record payload of only 1–3 bytes — the read triggers an IndexOutOfBoundsException. The exception handler calls select(ctx, null), which silently routes the connection to the default SslContext instead of the SNI-specific one. In deployments where the SNI-specific context enforces clientAuth=REQUIRE but the default context uses clientAuth=NONE or OPTIONAL, this converts a parsing error into a full mTLS bypass. Affected versions: all Netty prior to 4.1.137.Final and 4.2.0.Final through 4.2.16.Final.

Third-party scanners auto-labeled this CRITICAL at CVSS 9.1, but the GitHub advisory from the Netty project itself rates it High. The Netty project's rating is closer to reality. The CVSS vector uses AC:L (low attack complexity), which is misleading — the chain only fires when three simultaneous configuration conditions are met: SNI-based mTLS routing is in use, the default SslContext is more permissive than the SNI-specific one, and there is no application-layer certificate verification. Most Netty deployments use a single SslContext and never touch SslClientHelloHandler at all. Adjusting for real-world attack complexity (AC:H) yields CVSS 7.4, which better reflects the conditional nature of this bug.

"Netty mTLS bypass is real but needs a niche config most deployments don't use"
02 · The Attack Path

4 steps from start to impact.

STEP 01

Identify a Netty service using SNI-based TLS routing

The attacker needs to find a TLS endpoint backed by Netty that uses SslClientHelloHandler for SNI-based context selection — typically an API gateway, multi-tenant TLS termination proxy, or service mesh ingress. Scanning for server banners is unreliable since Netty doesn't advertise itself, but TLS fingerprinting (JA3/JA4 hashes) can narrow the field. The attacker tests multiple SNI values to confirm the server differentiates behavior by hostname.
Conditions required:
  • Target runs Netty < 4.1.137.Final or 4.2.x < 4.2.17.Final
  • Target uses SslClientHelloHandler for SNI-based SslContext selection
  • TLS endpoint is network-reachable
Where this breaks in practice:
  • Most Netty deployments use a single SslContext — SNI-based routing with per-host mTLS is a niche pattern
  • Netty is typically embedded in higher-level frameworks (Spring WebFlux, gRPC-Java, Vert.x) that abstract away SslClientHelloHandler
Detection/coverage: Network IDS/TLS inspection tools can flag unusually small TLS record payloads (1–3 bytes) in ClientHello messages.
STEP 02

Craft a fragmented TLS ClientHello

The attacker constructs a TLS ClientHello message split across multiple records, with the first record containing only 1–3 bytes of handshake payload. This is enough to pass the buggy bounds check but insufficient for the 4-byte handshake header read, triggering the IndexOutOfBoundsException. No specialized tooling has been publicly released; the attacker would need to use a raw socket or a modified TLS library (e.g., scapy, custom OpenSSL s_client wrapper, or a purpose-built Python script using the struct module).
Conditions required:
  • Ability to send raw TCP/TLS traffic to the target port
  • Understanding of TLS record layer framing
Where this breaks in practice:
  • No public PoC or weaponized tool exists as of September 2026
  • Requires TLS-layer crafting knowledge, not a point-and-click exploit
Detection/coverage: WAF or TLS-aware IDS rules can detect ClientHello records with payloads below 4 bytes — this is anomalous per RFC 8446.
STEP 03

Trigger fallback to default SslContext

The malformed ClientHello causes SslClientHelloHandler#decode to throw IndexOutOfBoundsException. The exception handler invokes select(ctx, null), routing the connection to the default SslContext. If the default context has clientAuth=NONE or clientAuth=OPTIONAL, the TLS handshake completes without requiring a client certificate. The attacker's connection is now established under the permissive default context.
Conditions required:
  • Default SslContext uses clientAuth=NONE or clientAuth=OPTIONAL
  • SNI-specific context with clientAuth=REQUIRE is the sole mTLS enforcement point
Where this breaks in practice:
  • Security-conscious deployments set the default context to clientAuth=REQUIRE as well
  • Some frameworks (e.g., Spring Cloud Gateway) add application-layer cert checks that would reject the certificate-less session
Detection/coverage: Server-side audit logs should show a TLS session established without a client certificate on a route that requires one — correlate with Netty handler logs for select(ctx, null) invocations.
STEP 04

Access mTLS-protected resources without a client certificate

With the TLS session established under the permissive default context, the attacker sends HTTP/gRPC/custom-protocol requests to the service. Because the mTLS gate was the sole authentication barrier, the attacker now has unauthenticated access to whatever the protected route serves. The blast radius depends on what sits behind that mTLS gate: internal APIs, admin endpoints, inter-service communication, or data-tier access.
Conditions required:
  • No application-layer authentication (e.g., JWT, API key, OAuth) behind the mTLS gate
  • Protected route serves sensitive functionality or data
Where this breaks in practice:
  • Defense-in-depth deployments layer application-layer auth on top of mTLS
  • Service mesh sidecars (Envoy, Linkerd) may enforce their own mTLS independently of the Netty application
Detection/coverage: Application-layer access logs will show requests from a client with no certificate identity — anomalous in mTLS environments. SIEM correlation rules for missing client cert fields in access logs would catch this.
03 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationNo evidence of active exploitation as of 2026-09-20. Not listed on CISA KEV. No campaigns or threat actor TTPs observed.
Proof-of-ConceptNo public PoC exists. The technical mechanism is fully documented in the OX Security analysis and the GHSA advisory, making a PoC straightforward to build for anyone with TLS record-layer knowledge.
EPSS0.00317 (0.32%) — 24.4th percentile. Low predicted probability of exploitation within 30 days.
KEV StatusNot listed. No due date. No binding operational directive applies.
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N (9.1) per third-party databases. GitHub advisory rates High. noisgate assessment: AC:H is more accurate → 7.4.
Affected VersionsNetty < 4.1.137.Final and 4.2.0.Final through 4.2.16.Final. The netty-handler artifact specifically contains the vulnerable SslClientHelloHandler.
Fixed Versions4.1.137.Final (4.1.x branch) and 4.2.17.Final (4.2.x branch). Distro backports: check downstream advisories for Spring Boot, Quarkus, gRPC-Java, Elasticsearch, Cassandra BOMs.
Scanning / ExposureNetty does not expose a fingerprint-able banner. Shodan/Censys cannot directly enumerate vulnerable instances. Dependency scanning (Snyk, Dependabot, Trivy, Grype) flags netty-handler JARs — this is the primary detection vector.
Disclosure Date2026-08-19 (public advisory). GHSA published 2026-09-08.
Reportervioletagg — Netty project contributor / maintainer.
04 · The Call

Final Verdict
= UNCHANGED to HIGH (7.4/10)

Why this verdict

  • Configuration-gated attack path: The exploit requires three simultaneous conditions — SNI-based SslContext routing with per-host clientAuth=REQUIRE, a default context with weaker auth, and no app-layer cert check. This is a conjunction of niche settings, not a default configuration. Real-world attack complexity is HIGH, not LOW as the raw CVSS vector claims.
  • No weaponization yet: Zero public PoC, zero in-the-wild exploitation, not on CISA KEV, and EPSS is 0.32% (24th percentile). The technical writeup is detailed enough to enable exploit development, but nobody has published tooling as of September 2026.
  • Massive library footprint, tiny vulnerable surface: Netty is embedded in hundreds of Java frameworks and products (Spring WebFlux, gRPC-Java, Elasticsearch, Cassandra, Play, Vert.x). However, SslClientHelloHandler is a specialized class — most deployments never instantiate it. The population of actually-exploitable servers is a small fraction of the Netty installed base.
  • Role multiplier: When SNI-based mTLS IS used, it's typically in high-value roles: (a) API gateways / service mesh ingress — blast radius is access to all backend services, potentially fleet-scale lateral movement; (b) multi-tenant TLS termination — blast radius is cross-tenant access. These roles establish a HIGH floor because the chain succeeds in the high-value role and the outcome is unauthorized access to internal service fabric. However, the affected component is not *canonically* a high-value-role component (Netty is a general-purpose networking library, not an IdP/DC/hypervisor) — fewer than 5% of Netty deployments use the vulnerable SNI mTLS pattern — so the floor is HIGH, not CRITICAL.
  • Unauthenticated remote vector preserves severity: Despite the configuration prerequisites, the attack IS network-reachable, requires no credentials, and no user interaction. When conditions are met, impact is high-confidentiality + high-integrity (full mTLS bypass). This prevents dropping below HIGH.

Why not higher?

CRITICAL would require either active exploitation, a canonical high-value-role component (Netty is a general-purpose library, not an identity provider or hypervisor), or a default-configuration attack path. None apply. The three-condition conjunction for exploitability dramatically narrows the vulnerable population. Automated scanners rating this 9.1/CRITICAL are reflecting the theoretical worst-case CVSS vector, not real deployment exposure.

Why not lower?

MEDIUM would undercount the blast radius in the deployments where the conditions ARE met. An mTLS bypass on an API gateway or service mesh ingress gives an unauthenticated remote attacker access to the entire internal service fabric — that's a domain-level impact. The unauthenticated-remote vector with high C+I impact, combined with a fully documented exploit mechanism that any competent attacker could weaponize, keeps this firmly at HIGH.

05 · Compensating Control

What to do — in priority order.

  1. Set the default SslContext to clientAuth=REQUIRE — The root cause of the bypass is falling back to a permissive default. If the default context also requires client certificates, the fallback is harmless. This is a one-line configuration change and the single most effective mitigation. Deploy within 30 days per the noisgate mitigation SLA for HIGH severity.
  2. Add application-layer certificate verification — In your Netty ChannelHandler pipeline, verify the peer certificate's CN/SAN against an allowlist after the TLS handshake completes. This defense-in-depth measure ensures mTLS enforcement doesn't depend solely on SslContext selection. Libraries like Bouncy Castle or standard javax.net.ssl.SSLSession#getPeerCertificates() make this straightforward.
  3. Deploy TLS-aware IDS rules for anomalous ClientHello records — Write Suricata/Zeek rules to alert on TLS records with handshake payloads under 4 bytes. This is anomalous per RFC 8446 and would detect exploitation attempts. Example: alert tls any any -> any any (msg:"Suspicious tiny TLS record payload"; flow:to_server; content:|16 03|; depth:2; dsize:<9;).
  4. Upgrade netty-handler to 4.1.137.Final or 4.2.17.Final — The definitive fix. Ensure both direct and transitive dependencies are updated — check your Maven/Gradle BOM. Target within 180 days per the noisgate remediation SLA for HIGH severity. Run mvn dependency:tree -Dincludes=io.netty:netty-handler to find all transitive pulls.
  5. Enforce mTLS at the service mesh sidecar layer — If running Istio/Linkerd/Consul Connect, ensure sidecar-level mTLS is enforced independently of the application's Netty configuration. This provides a second authentication gate that the Netty bypass cannot circumvent.
What doesn't work
  • WAF rules blocking malformed HTTP requests — the bypass occurs at the TLS layer, before any HTTP parsing. A WAF that operates on decrypted HTTP traffic will never see the malicious ClientHello.
  • Network-layer firewalling / IP allowlists alone — these control who can reach the port but do not validate whether the TLS handshake enforced client authentication. An attacker from an allowed IP range still bypasses mTLS.
  • Upgrading only the application's direct Netty dependency — transitive dependencies through Spring Boot, gRPC-Java, or Elasticsearch client libraries may pin an older netty-handler. You must audit the full dependency tree.
06 · Verification

Crowdsourced verification payload.

Run this script on each application host where a Java service uses Netty. It scans for netty-handler JAR files in common deployment paths and checks their version. Requires read access to the filesystem (no root needed). Invoke: bash check_cve_2026_75595.sh /opt/myapp/lib (pass the directory containing your application's JARs).

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cve_2026_75595.sh — Detect CVE-2026-75595 (Netty SslClientHelloHandler mTLS bypass)
# Usage: bash check_cve_2026_75595.sh [search_directory]
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN

set -euo pipefail

SEARCH_DIR="${1:-/}"
VULNERABLE=0
PATCHED=0
FOUND=0

version_gte() {
  # Returns 0 if $1 >= $2 using sort -V
  [ "$(printf '%s\n%s' "$1" "$2" | sort -V | head -n1)" = "$2" ]
}

echo "[*] Scanning for netty-handler JARs in ${SEARCH_DIR}..."

while IFS= read -r jar; do
  FOUND=$((FOUND + 1))
  # Extract version from filename: netty-handler-4.1.136.Final.jar
  version=$(echo "$jar" | grep -oP 'netty-handler-\K[0-9]+\.[0-9]+\.[0-9]+')
  if [ -z "$version" ]; then
    # Try reading from META-INF/MANIFEST.MF inside the JAR
    version=$(unzip -p "$jar" META-INF/MANIFEST.MF 2>/dev/null | grep -i 'Bundle-Version\|Implementation-Version' | head -1 | grep -oP '[0-9]+\.[0-9]+\.[0-9]+' || true)
  fi
  if [ -z "$version" ]; then
    echo "[?] UNKNOWN version: $jar"
    continue
  fi

  major_minor=$(echo "$version" | cut -d. -f1,2)
  if [ "$major_minor" = "4.2" ]; then
    if version_gte "$version" "4.2.17"; then
      echo "[+] PATCHED ($version): $jar"
      PATCHED=$((PATCHED + 1))
    else
      echo "[-] VULNERABLE ($version < 4.2.17): $jar"
      VULNERABLE=$((VULNERABLE + 1))
    fi
  elif [ "$major_minor" = "4.1" ]; then
    if version_gte "$version" "4.1.137"; then
      echo "[+] PATCHED ($version): $jar"
      PATCHED=$((PATCHED + 1))
    else
      echo "[-] VULNERABLE ($version < 4.1.137): $jar"
      VULNERABLE=$((VULNERABLE + 1))
    fi
  else
    # Versions before 4.1 are also vulnerable
    echo "[-] VULNERABLE ($version): $jar"
    VULNERABLE=$((VULNERABLE + 1))
  fi
done < <(find "$SEARCH_DIR" -name 'netty-handler-*.jar' -type f 2>/dev/null)

echo ""
echo "=== RESULTS ==="
echo "JARs found: $FOUND | Vulnerable: $VULNERABLE | Patched: $PATCHED"

if [ "$FOUND" -eq 0 ]; then
  echo "UNKNOWN — no netty-handler JARs found in $SEARCH_DIR"
  exit 2
elif [ "$VULNERABLE" -gt 0 ]; then
  echo "VULNERABLE — CVE-2026-75595 affects $VULNERABLE JAR(s)"
  exit 1
else
  echo "PATCHED — all netty-handler JARs are at fixed versions"
  exit 0
fi
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.