GHSA-42cj-m3vj-89wv Traefik CRD IngressRouteTCP ServersTransport Cross-Provider Namespace Bypass
SummaryThere is a medium-severity cross-provider reference vulnerability in Traefik's Kubernetes CRD provider. The `crossProviderNamespaces` allowlist is enforced for HTTP `serversTransport` references but was not enforced for `IngressRouteTCP` service `serversTransport` references. A low-privileged Kubernetes user in a namespace that is not listed in `crossProviderNamespaces` could set `serversTransport: foo@file` on an `IngressRouteTCP` service, causing Traefik to accept the forbidden cross-provider reference and use the file-provider `TCPServersTransport` — including privileged backend mTLS client certificates, SPIFFE identity, or PROXY-protocol settings. The fix applies the `crossProviderNamespaces` allowlist to TCP `serversTransport` references.Patcheshttps://github.com/traefik/traefik/releases/tag/v3.6.23https://github.com/traefik/traefik/releases/tag/v3.7.7For more informationIf you have any questions or comments about this advisory, please [open an issue](https://github.com/traefik/traefik/issues).SummaryTraefik's Kubernetes CRD provider enforces `crossProviderNamespaces` for several
cross-provider references, but `IngressRouteTCP` service
`serversTransport` references skip that allowlist. A low-privileged Kubernetes
user in a namespace that is not listed in `crossProviderNamespaces` can still
set `serversTransport: foo@file` on an `IngressRouteTCP` service. Traefik
accepts the forbidden cross-provider reference and later uses the referenced
`TCPServersTransport`, including privileged backend mTLS client certificates,
SPIFFE identity, or PROXY protocol settings.Description`crossProviderNamespaces` is documented and implemented as an allowlist for
namespaces that may declare cross-provider references from Kubernetes CRD
objects. HTTP `serversTransport` references enforce that allowlist. TCP
`serversTransport` references do not.An attacker with low Kubernetes privileges in namespace `default` can create an
`IngressRouteTCP` service with:Even when the provider is configured with:Traefik still emits a TCP dynamic service whose load balancer points to
`foo@file`. At runtime, `DialerManager.Build()` uses the exact referenced
transport name and applies that transport's TLS client certificates and related
backend-connection settings.ImpactThe PoC demonstrates two positive facts:A namespace outside `crossProviderNamespaces` can cause Traefik to accept and
store `LoadBalancer.ServersTransport = "foo@file"` from an
`IngressRouteTCP` service.A qualified `foo@file` `TCPServersTransport` with a client certificate is
actually consumed by the TCP dialer and presented to an mTLS backend.This proves a backend identity relay primitive: a lower-privileged CRD author
can make Traefik connect to a backend using an operator-defined cross-provider
transport identity that the namespace should not be allowed to reference.Proof Of ConceptFiles`run.sh`: portable runner.`poc_crd_test.go`: positive CRD provider proof.`with_servers_transport_cross_provider_poc.yml`: minimal
`IngressRouteTCP` fixture.`poc_tcp_mtls_test.go`: positive runtime mTLS identity-use proof.Requirements`git`Go toolchain compatible with the target Traefik tag. `v3.7.5` uses
`go 1.25.0`.Network access to clone `https://github.com/traefik/traefik.git` and download
Go modules on first run.No local Traefik checkout is required by default.RunOptional target override:Optional local-source override for faster local validation:Expected ResultThe run should end with:Root CauseLine numbers below are from:1. The provider option is meant to cover IngressRouteTCP`pkg/provider/kubernetes/crd/kubernetes.go:60`This establishes the security invariant: `IngressRouteTCP` cross-provider
references should be gated by `crossProviderNamespaces`.2. TCP service creation forwards the attacker-controlled transport name`pkg/provider/kubernetes/crd/kubernetes_tcp.go:183-185`The attacker-controlled `serversTransport` field is passed into the key builder.3. TCP key builder returns cross-provider names without the allowlist check`pkg/provider/kubernetes/crd/kubernetes_tcp.go:321-322`This accepts `foo@file` directly. There is no call to
`isCrossProviderNamespaceAllowed(...)` on this TCP path.4. HTTP sibling contains the missing authorization gate`pkg/provider/kubernetes/crd/kubernetes_http.go:507-508`The HTTP path proves the intended policy: cross-provider `serversTransport`
references should be rejected when the route namespace is not in the allowlist.5. Runtime TCP dialer consumes the exact referenced transport`pkg/tcp/dialer.go:135-141``pkg/tcp/dialer.go:183-188`The accepted `foo@file` reference is not a harmless string. It selects the
cross-provider transport and applies its client TLS identity during backend
connections.
CVSS v4.0 score: 5.3