Mar 20, 2026·6 min read·4 visits
A flaw in Traefik's custom SNI pre-sniffing logic allows unauthenticated attackers to bypass route-specific mTLS requirements by transmitting a artificially fragmented TLS ClientHello message.
Traefik versions up to 2.11.40 and 3.6.10 are vulnerable to a mutual TLS (mTLS) bypass. The vulnerability occurs in the TLS Server Name Indication (SNI) pre-sniffing logic when handling fragmented ClientHello packets. This extraction failure results in the proxy falling back to a global default TLS configuration, which allows attackers to bypass route-level mTLS authentication requirements.
Traefik operates as a widely deployed HTTP reverse proxy and load balancer. A core security feature of Traefik is the ability to enforce mutual TLS (mTLS) authentication on specific routing paths. This feature ensures that only clients presenting a cryptographically valid certificate can access protected internal upstream services.
CVE-2026-32305 is classified as an Improper Authentication (CWE-287) and Insecure Default Initialization of Resource (CWE-1188) vulnerability. The flaw exists entirely within Traefik's custom connection sniffing logic. This logic is used to route incoming TLS connections before the formal cryptographic handshake is completed by the standard library.
When processing incoming TLS packets, Traefik attempts to extract the Server Name Indication (SNI) extension early in the connection lifecycle. If this early extraction fails, Traefik silently falls back to a global default TLS configuration. An attacker can manipulate this behavior to bypass route-specific mTLS constraints completely.
The vulnerability is isolated to the ServeTCP function located within router.go. Traefik attempts to "pre-sniff" the SNI from the incoming connection to determine which specific TLS configuration and routing rules to apply. This pre-sniffing process relies on the internal clientHelloInfo function to peek at the initial bytes of the connection stream without consuming them.
The sniffing logic evaluates the first TLS record to read its length, which is temporarily stored as recLen. It then attempts to read exactly 5 + recLen bytes to parse the entire ClientHello message into a readable structure. This implementation assumes that the complete ClientHello message fits within a single contiguous TLS record, a common behavior that is not strictly mandated by the TLS protocol specification.
If a client transmits a ClientHello that is explicitly fragmented across multiple TLS records, the peeked data segment is incomplete. The custom TLS parser encounters an unexpected end of data and throws an EOF error. As a direct result of the unhandled error state, the parser returns an empty string for the SNI value.
Because the SNI string evaluates as empty, the Traefik routing engine cannot match the incoming request to a specific, host-based routing rule during the pre-sniffing phase. Traefik resolves this undetermined routing state by applying the global default TLS configuration. If this default configuration is configured as NoClientCert, the subsequent standard Go standard library TLS handshake proceeds without requesting or verifying a client certificate.
Exploitation requires an attacker to deliberately fragment their initial TLS handshake. The attacker initiates a standard TCP connection to the Traefik entrypoint and begins the TLS handshake sequence. Instead of transmitting a standard ClientHello message within a single record, the attacker limits the maximum record size to split the message into multiple smaller cryptographic records.
The fragmentation boundaries must be specifically aligned so that the SNI extension data falls entirely outside the first TLS record. When Traefik processes this manipulated connection, the EOF error is reliably triggered within the pre-sniffing phase. The connection stream is then handed over to the standard Go crypto/tls library for the actual cryptographic handshake.
from tlsfuzzer.runner import Runner
from tlsfuzzer.messages import Connect, SetMaxRecordSize, ClientHelloGenerator
# ... standard tlsfuzzer imports omitted for brevity
def main():
# Set an artificially small record size to force fragmentation
record_size = 500
sni = "protected-service.internal"
conv = Connect("127.0.0.1", 8443)
node = conv.add_child(SetMaxRecordSize(record_size))
# SNI extension pushed beyond the initial record size limit
ext = {
ExtensionType.server_name: SNIExtension().create(bytearray(sni, "ascii")),
}
node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext))
node = node.add_child(ExpectServerHello())
Runner(conv).run()Once the standard Go library assumes control of the connection socket, it successfully reads the remaining records, reassembles the fragmented ClientHello, and completes the handshake using the fallback permissive TLS policy. After the secure channel is established, the attacker transmits an HTTP request specifying a Host header that targets the protected internal service. Traefik processes the authorized HTTP request and routes it to the backend, completely bypassing the intended route-level mTLS enforcement.
The vulnerability carries a CVSS v4.0 base score of 7.8, reflecting a high severity security defect combined with a low attack complexity. The attack requires absolutely no prior authentication, requires no user interaction, and can be executed remotely from any position with network access to the proxy listener.
The primary security consequence is a complete bypass of intended authentication and access controls for the affected routing paths. Organizations relying on Traefik as an edge ingress controller to enforce Zero Trust network access parameters via mTLS are directly exposed. Attackers can reach internal microservices, administrative interfaces, or sensitive data stores that architectural models assumed to be cryptographically isolated.
While the vulnerability permits unauthorized routing to protected endpoints, the ultimate impact on system confidentiality and integrity depends entirely on the security posture of the exposed backend services. Traefik itself is not compromised, nor does this flaw provide a direct vector for remote code execution on the underlying proxy host system.
The maintainers addressed the core issue in Traefik versions 2.11.41, 3.6.11, and 3.7.0-ea.2. The security patch fundamentally alters the initial connection handling logic to correctly process multi-record ClientHello messages. The fix implemented in Pull Request #12787 delegates the fragmented record processing directly to the robust Go standard library, rather than relying on brittle custom byte-peeking logic.
If immediate software patching is not feasible, system administrators must alter the global default TLS configuration as a compensating control. The default policy must be explicitly hardened to enforce mTLS globally utilizing the RequireAndVerifyClientCert directive. This ensures that any routing failure resulting in an empty SNI correctly defaults to a restrictive security posture rather than a permissive one.
tls:
options:
default:
clientAuth:
caFiles:
- /path/to/ca.crt
clientAuthType: RequireAndVerifyClientCertImplementing this specific configuration workaround requires administrators to explicitly define permissive TLS options (NoClientCert) for all intended public-facing routes. This inverts the proxy's default behavior and establishes a fail-closed security architecture. Network security monitoring systems should also be configured to generate alerts for heavily fragmented TLS ClientHello packets.
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:H/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Traefik Traefik Labs | <= 2.11.40 | 2.11.41 |
Traefik Traefik Labs | >= 3.0.0-beta1, <= 3.6.10 | 3.6.11 |
Traefik Traefik Labs | = 3.7.0-ea.1 | 3.7.0-ea.2 |
| Attribute | Detail |
|---|---|
| Attack Vector | Network |
| CWE ID | CWE-287, CWE-1188 |
| CVSS v4.0 | 7.8 |
| EPSS Score | 0.00046 (13.81%) |
| Exploit Status | Proof-of-Concept Available |
| KEV Status | Not Listed |
Improper Authentication and Insecure Default Initialization of Resource resulting in mTLS bypass.