# Traefik — CWE-407 Disclosure Brief
**2026-03-27 · Patch available — awaiting upstream merge**

## Finding

Three O(n²) defects in Traefik's middleware, observability, and config-loading subsystems. All three use `slices.Contains` over slices in hot paths — two fire on every request, one fires on every router during config loading. All patched. Speedup: 20× across all three.

## The Defects

**traefik-0001 (PATCHED — HIGH):** `pkg/middlewares/forwardedheaders/forwarded_header.go:229`

```go
// Per request — for each incoming header:
if slices.Contains(xHeaders, headerName) {
    // O(H) scan per header per request
}
```

`slices.Contains(xHeaders, headerName)` called per incoming header on every request through the forwarded-headers middleware. For H trusted header names and K headers per request: **O(K × H) per request**. Fix: `map[string]struct{}` pre-built at middleware init. **Measured ratio: 20×.**

**traefik-0002 (PATCHED — HIGH):** `pkg/observability/tracing/tracing.go:230`

```go
// Per request — for each URL query parameter:
if slices.Contains(safeQueryParams, paramName) {
    // O(Q×P) scan per request for URL redaction
}
```

`slices.Contains(safeQueryParams, paramName)` called for every URL query parameter on every traced request. For P safe-param names and Q query parameters per request: **O(Q × P) per request**. Fix: `map[string]struct{}` pre-built at tracer init. **Measured ratio: 20×.**

**traefik-0003 (PATCHED — MEDIUM):** `pkg/config/runtime/runtime_http.go:30`

```go
// During config loading — for each router:
for _, router := range routers {
    for _, ep := range router.EntryPoints {
        if slices.Contains(entryPoints, ep) {
            // O(R×E) total across all routers
        }
    }
}
```

`slices.Contains(entryPoints, ep)` inside a per-router, per-entry-point loop during config loading. For R routers and E entry points: **O(R × E)** total. Fix: pre-build `map[string]bool` from `entryPoints` before the router loop. **Measured ratio: 20×.**

## Complexity Proof

**traefik-0001:** Let H = len(xHeaders), K = headers per request, R = requests/second.
- Defective: O(K × H) per request → O(R × K × H) per second.
- Fixed: O(K) per request (map lookup) → O(R × K) per second.
- At H=20: **20× measured ratio.**

**traefik-0002:** Let P = len(safeQueryParams), Q = query params per request URL, R = requests/second.
- Defective: O(Q × P) per request.
- Fixed: O(Q) per request via map lookup.
- At P=20: **20× measured ratio.**

**traefik-0003:** Let R = number of routers, E = number of entry points, C = entry points per router.
- Defective: O(R × C × E) comparisons total during config load.
- Fixed: O(E) map build + O(R × C) lookups = O(R × C + E) total.
- At E=20 entry points: **20× reduction in entry-point comparisons.**

## Impact

traefik-0001 and traefik-0002 fire on every request passing through Traefik — the dominant cloud-native reverse proxy and ingress controller in Kubernetes environments. Traefik is deployed as the primary ingress for thousands of production Kubernetes clusters. traefik-0001 fires for every request using the forwarded-headers middleware (enabled by default in many configurations); traefik-0002 fires for every request with tracing enabled. traefik-0003 fires on every configuration reload, which in dynamic Kubernetes environments occurs frequently as services are deployed and scaled.

## The Fix

All three fixes follow the same pattern: replace `slices.Contains` over a slice with a `map[string]struct{}` pre-built once at init/config-load time.

```go
// Before (traefik-0001 representative)
if slices.Contains(xHeaders, headerName) { ... }  // O(H) per header per request

// After
// CWE-407 fix: map[string]struct{} for O(1) lookup instead of O(H) slices.Contains scan.
xHeaderSet := make(map[string]struct{}, len(xHeaders))
for _, h := range xHeaders {
    xHeaderSet[strings.ToLower(h)] = struct{}{}
}
// Per request:
if _, ok := xHeaderSet[headerName]; ok { ... }  // O(1)
```

Same pattern applied at `tracing.go:230` (safeQueryParams) and `runtime_http.go:30` (entryPoints).

## Patch

`defects/traefik/patch/traefik-0001-0002-0003-slices-map.patch`

## What We Ask

1. Confirm receipt and assign a GitHub Security Advisory or issue reference.
2. Validate the patch against forwarded-headers, tracing, and config-loading test suites.
3. Assess CVE eligibility — traefik-0001 and traefik-0002 fire on every request in production.
4. Coordinate a disclosure date — we are targeting 90 days from first contact.

Contact: see cover email. This brief is confidential until coordinated disclosure.
