70 lines
2.6 KiB
Markdown
70 lines
2.6 KiB
Markdown
# containerd — CWE-407 Disclosure Brief
|
|
**2026-03-27 · Patch available — awaiting upstream merge**
|
|
|
|
## Finding
|
|
|
|
One O(n²) defect in containerd's OCI spec options. `filterCaps` and `WithAddedCapabilities` use `slices.Contains` (via `capsContain()`) causing O(n²) capability set processing per container launch. Patch ready for upstream review.
|
|
|
|
## The Defects
|
|
|
|
**containerd-0001 (PATCHED — HIGH):** `pkg/oci/spec_opts.go:1069,1080`
|
|
|
|
```go
|
|
// filterCaps / WithAddedCapabilities — per container launch:
|
|
func capsContain(caps []string, s string) bool {
|
|
return slices.Contains(caps, s) // O(n) per cap check
|
|
}
|
|
// Called inside loop over all capabilities:
|
|
for _, cap := range allCaps {
|
|
if !capsContain(filteredCaps, cap) { // O(n²) total
|
|
...
|
|
}
|
|
}
|
|
```
|
|
|
|
`capsContain()` wraps `slices.Contains` and is called inside a loop over all capabilities. For N capabilities: **O(N²) per container launch**. Fix: `map[string]bool` capability set.
|
|
|
|
## Complexity Proof
|
|
|
|
For N capabilities (Linux has ~40 capabilities):
|
|
- Per container launch: O(N²) comparisons
|
|
- Fixed: `map[string]bool` cap set → O(N)
|
|
- At N=40: 1,600 comparisons vs 40 map lookups
|
|
- Scales with custom capability sets; notable for high container launch rate environments.
|
|
|
|
## Impact
|
|
|
|
All containerd deployments launching containers with capability filtering — virtually all production Kubernetes deployments (containerd is the default CRI). Container launches with `WithAddedCapabilities`, `WithDroppedCapabilities`, and `WithCapabilities` spec options all hit this path. Kubernetes nodes with high pod churn (auto-scalers, batch workloads, CI/CD systems) launch many containers per minute.
|
|
|
|
## The Fix
|
|
|
|
Replace `capsContain()` with a `map[string]bool` capability set:
|
|
|
|
```go
|
|
// Before
|
|
func capsContain(caps []string, s string) bool {
|
|
return slices.Contains(caps, s) // O(n)
|
|
}
|
|
|
|
// After
|
|
// CWE-407 fix: map[string]bool for O(1) cap check instead of O(n) slices.Contains.
|
|
func buildCapSet(caps []string) map[string]bool {
|
|
set := make(map[string]bool, len(caps))
|
|
for _, c := range caps { set[c] = true }
|
|
return set
|
|
}
|
|
// Use: capSet[cap] instead of capsContain(caps, cap)
|
|
```
|
|
|
|
## Patch
|
|
|
|
`defects/containerd/patch/containerd-0001-spec-opts-cap-map.patch`
|
|
|
|
## What We Ask
|
|
|
|
1. Confirm receipt and assign a GitHub Security Advisory or issue reference.
|
|
2. Validate the patch against your OCI spec and capability test suite.
|
|
3. Assess CVE eligibility — fires on every container launch with capability filtering.
|
|
4. Coordinate a disclosure date — we are targeting 90 days from first contact.
|
|
|
|
Contact: see cover email. This brief is confidential until coordinated disclosure.
|