There is a potential vulnerability in Traefik ACME TLS certificates' automatic generation: the ACME TLS-ALPN fast path can allow unauthenticated clients to tie up goroutines and file descriptors indefinitely when the ACME TLS challenge is enabled.
A malicious client can open many connections, send a minimal ClientHello with acme-tls/1, then stop responding, leading to denial of service of the entrypoint.
If you have any questions or comments about this advisory, please open an issue.
<details> <summary>Original Description</summary>
Dear Traefik security team,
We believe we have identified a resource-exhaustion issue in the ACME TLS-ALPN fast path that can allow unauthenticated clients to tie up goroutines and file descriptors indefinitely when the ACME TLS challenge is enabled.
pkg/server/router/tcp/router.go (ACME TLS-ALPN handling). acme-tls/1, Traefik intercepts it and calls tls.Server(...).Handshake() without any read/write deadlines and without closing the connection afterward. ```143:171:pkg/server/router/tcp/router.go // Deadlines are cleared before protocol dispatch if err := conn.SetDeadline(time.Time{}); err != nil { log.Error().Err(err).Msg("Error while setting deadline") }
// ACME TLS-ALPN fast path if !r.acmeTLSPassthrough && slices.Contains(hello.protos, tlsalpn01.ACMETLS1Protocol) { r.acmeTLSALPNHandler().ServeTCP(r.GetConn(conn, hello.peeked)) return }
```224:226:pkg/server/router/tcp/router.go
// Handler invoked by the branch above
return tcp.HandlerFunc(func(conn tcp.WriteCloser) {
_ = tls.Server(conn, r.httpsTLSConfig).Handshake()
})
acme-tls/1, then stop responding, leading to denial of service of the entrypoint. http.Server timeouts; this bespoke path bypasses them.allowACMEByPass disabled for the entrypoint (the default when ACME TLS challenge is handled by Traefik).@@ func (r *Router) acmeTLSALPNHandler() tcp.Handler {
- return tcp.HandlerFunc(func(conn tcp.WriteCloser) {
- _ = tls.Server(conn, r.httpsTLSConfig).Handshake()
- })
+ return tcp.HandlerFunc(func(conn tcp.WriteCloser) {
+ // Ensure the handshake cannot block indefinitely and always closes the socket.
+ _ = conn.SetReadDeadline(time.Now().Add(10 * time.Second))
+ _ = conn.SetWriteDeadline(time.Now().Add(10 * time.Second))
+
+ tlsConn := tls.Server(conn, r.httpsTLSConfig)
+ _ = tlsConn.Handshake()
+ _ = tlsConn.Close() // close regardless of handshake outcome
+ })
}
Alternatively, route ACME TLS-ALPN through the existing tcp.TLSHandler/HTTP server path so the configured timeouts and lifecycle management apply automatically.
Please let us know if you would like a PoC or further details. We have not made any code changes in this report.
Let us know if you have any questions or need clarification!
Best wishes,
Pavel Kohout
Aisle Research
</details>
{
"cwe_ids": [
"CWE-770"
],
"severity": "MODERATE",
"nvd_published_at": "2026-01-15T23:15:51Z",
"github_reviewed": true,
"github_reviewed_at": "2026-01-15T22:58:23Z"
}