wave7: 433/194 — kafka/flink/pulsar, spring/micronaut/quarkus, nginx/haproxy/traefik, linux/nomad/consul, numpy/pandas/sklearn, ES/OS/pg/sqlite/rustc/cargo

This commit is contained in:
russell@unturf.com 2026-03-27 16:20:58 -04:00
parent 3735145aa5
commit 5fe6da7cc2
69 changed files with 6793 additions and 32 deletions

View file

@ -0,0 +1,87 @@
# traefik-0001 — XForwarded.removeConnectionHeaders slices.Contains O(H×F) per request
## Ecosystem
traefik (Go)
## Severity
HIGH — triggered on every proxied HTTP request
## Location
`pkg/middlewares/forwardedheaders/forwarded_header.go`
Function: `removeConnectionHeaders`
## Description
Every HTTP request processed by the XForwarded middleware calls
`removeConnectionHeaders`. Inside that function, for each value in the
`Connection` header (H values), the code calls `slices.Contains` twice:
```go
for _, f := range req.Header[connection] { // outer: H Connection values
for sf := range strings.SplitSeq(f, ",") { // outer: split tokens
key := http.CanonicalHeaderKey(sf)
if slices.Contains(xHeaders, key) { // O(11) linear scan
continue
}
if slices.Contains(x.connectionHeaders, key) { // O(C) linear scan
...
}
}
}
```
- `xHeaders` is a package-level `[]string` of 11 fixed header names.
- `x.connectionHeaders` is a user-configured `[]string` of allowed headers
(can be many entries in large deployments).
Complexity: O(H × (11 + C)) per request where H = Connection header token
count and C = len(connectionHeaders).
The fix converts both slices to `map[string]struct{}` at construction time,
making each lookup O(1).
## CWE
CWE-407: Inefficient Algorithmic Complexity (linear membership test inside loop)
## Fix
### forwarded_header.go — struct change
```go
type XForwarded struct {
...
// was: connectionHeaders []string
xHeadersSet map[string]struct{} // pre-built from package xHeaders slice
connectionHeadersSet map[string]struct{}
...
}
```
### NewXForwarded — build maps at construction
```go
xHeadersSet := make(map[string]struct{}, len(xHeaders))
for _, h := range xHeaders {
xHeadersSet[h] = struct{}{}
}
connectionHeadersSet := make(map[string]struct{}, len(connectionHeaders))
for _, h := range canonicalConnectionHeaders {
connectionHeadersSet[h] = struct{}{}
}
```
### removeConnectionHeaders — O(1) lookups
```go
if _, ok := x.xHeadersSet[key]; ok {
continue
}
if _, ok := x.connectionHeadersSet[key]; ok {
connectionHopByHopHeaders = append(connectionHopByHopHeaders, key)
continue
}
```
## Speedup
xHeaders scan: 11x (constant), connectionHeaders scan: O(C) → O(1).
At C=100 user-configured headers, 100x reduction in inner work per
Connection token.
## Status
PATCHED (patch in this file)

View file

@ -0,0 +1,71 @@
# traefik-0002 — Tracer.safeURL slices.Contains O(Q×P) per request
## Ecosystem
traefik (Go)
## Severity
MEDIUM — triggered on every traced HTTP request when safeQueryParams is configured
## Location
`pkg/observability/tracing/tracing.go`
Function: `safeURL`
## Description
`safeURL` is called on every traced HTTP request to redact query parameters
that are not in the safe list. For each of Q query parameters in the URL,
it calls `slices.Contains(t.safeQueryParams, k)` which is an O(P) linear scan:
```go
query := redactedURL.Query()
for k := range query { // O(Q) outer
if slices.Contains(t.safeQueryParams, k) { // O(P) inner scan
continue
}
query.Set(k, "REDACTED")
}
```
Complexity: O(Q × P) per traced request, where Q = query param count
and P = len(safeQueryParams).
`safeQueryParams` is fixed at construction time; it can be pre-built
into a `map[string]struct{}` making each lookup O(1).
## CWE
CWE-407: Inefficient Algorithmic Complexity
## Fix
### Tracer struct — add pre-built set
```go
type Tracer struct {
...
safeQueryParams []string // keep for config inspection
safeQueryParamsSet map[string]struct{} // pre-built O(1) lookup
...
}
```
### NewTracer — build set at construction
```go
safeQueryParamsSet := make(map[string]struct{}, len(safeQueryParams))
for _, p := range safeQueryParams {
safeQueryParamsSet[p] = struct{}{}
}
```
### safeURL — O(1) lookup
```go
for k := range query {
if _, ok := t.safeQueryParamsSet[k]; ok {
continue
}
query.Set(k, "REDACTED")
}
```
## Speedup
P=20 safe params, Q=30 query params: 20x reduction per request.
## Status
PATCHED (patch in this file)

View file

@ -0,0 +1,65 @@
# traefik-0003 — runtime PopulateUsedBy entryPoints slices.Contains O(R×M×E) config load
## Ecosystem
traefik (Go)
## Severity
MEDIUM — config reload path; scales poorly with many routers + entry points
## Location
- `pkg/config/runtime/runtime_http.go` function `PopulateUsedBy`
- `pkg/config/runtime/runtime_tcp.go` function `PopulateUsedBy`
- `pkg/config/runtime/runtime_udp.go` function `PopulateUsedBy`
## Description
All three `PopulateUsedBy` functions have the same pattern:
```go
for rtName, rt := range c.Routers { // O(R) outer: R routers
for _, entryPointName := range rt.EntryPoints { // O(M) middle: M EPs per router
if !slices.Contains(entryPoints, entryPointName) { // O(E) inner scan
...
}
}
}
```
`entryPoints` is a `[]string` passed in, containing all configured entry
point names. The `slices.Contains` call does a linear scan of E names
for every (router, entryPoint) pair.
Complexity: O(R × M × E) per config reload.
In large Kubernetes deployments: R=1000 routers, M=3 entry points each,
E=20 entry points → 60,000 linear comparisons per reload.
Fix: pre-build `entryPointsSet := make(map[string]bool)` from the
`entryPoints` slice before the outer loop. Each lookup becomes O(1).
## CWE
CWE-407: Inefficient Algorithmic Complexity
## Fix (all three files, same pattern)
```go
// Pre-build O(1) lookup set before the loop.
entryPointsSet := make(map[string]bool, len(entryPoints))
for _, ep := range entryPoints {
entryPointsSet[ep] = true
}
for rtName, rt := range c.Routers {
for _, entryPointName := range rt.EntryPoints {
if !entryPointsSet[entryPointName] { // O(1)
rt.AddError(...)
continue
}
...
}
}
```
## Speedup
E=20 entry points: 20x reduction in inner work per config reload.
## Status
PATCHED (patch in this file)