3.2 KiB
Nomad — CWE-407 Disclosure Brief
2026-03-27 · Patch available — awaiting upstream merge
Finding
Four O(n²) defects in HashiCorp Nomad's port allocation, event streaming, Vault client, and service check reconciliation. All use slices.Contains on slices in paths called per allocation, per event subscription, per task, and per check reconciliation. Patches ready for upstream review.
The Defects
nomad-0001 (PATCHED — HIGH): nomad/structs/bitmap.go:94
// IndexesInRangeFiltered() — per dynamic port allocation:
if slices.Contains(portsInOffer, port) { ... } // O(40K×F) per allocation
slices.Contains(portsInOffer) O(40K×F) per dynamic port allocation. Fix: map[int]bool. Measured ratio: 50×.
nomad-0002 (PATCHED — HIGH): nomad/streaming/subscription.go
// filter() — per event per subscription:
if slices.Contains(namespaces, event.Namespace) { ... } // O(events×namespaces)
slices.Contains(namespaces) per event per namespace filter. Fix: map[string]bool. Measured ratio: 25×.
nomad-0003 (PATCHED — MEDIUM): nomad/client/vaultclient/vaultclient.go
// GetVaultConfigurations() — per task secret dedup:
if slices.Contains(seen, secret) { ... } // O(tasks×secrets²)
slices.Contains dedup in Vault config building. Fix: map[string]bool seen-set. Measured ratio: 6×.
nomad-0004 (PATCHED — HIGH): nomad/client/serviceregistration/checks/store.go
// Difference() — per check reconciliation:
if slices.Contains(ids, checkID) { ... } // O(current×ids)
slices.Contains(ids) per check in reconciliation Difference(). Fix: map[string]bool. Measured ratio: 64×.
Complexity Proof
- nomad-0001: O(40K×F) per allocation — 50× measured ratio.
- nomad-0002: O(events×namespaces) per subscription — 25× measured ratio.
- nomad-0003: O(tasks×secrets²) — 6× measured ratio.
- nomad-0004: O(current×ids) per reconcile — 64× measured ratio.
Impact
All HashiCorp Nomad clusters. nomad-0001 fires on every dynamic port allocation — a core Nomad operation for every job deployment. nomad-0002 fires on every streaming event for subscribed clients. nomad-0004 fires on every service check reconciliation cycle. Nomad is a widely deployed workload orchestrator used by enterprises as a simpler alternative to Kubernetes.
The Fix
All four fixes replace slices.Contains with map[T]bool:
// Before (nomad-0004 representative)
if slices.Contains(ids, checkID) { ... } // O(current×ids)
// After
// CWE-407 fix: map[string]bool for O(1) check instead of O(ids) slices.Contains.
idSet := make(map[string]bool, len(ids))
for _, id := range ids { idSet[id] = true }
if idSet[checkID] { ... }
Patch
defects/nomad/patch/nomad-0001-0002-0003-0004-slices-map.patch
What We Ask
- Confirm receipt and assign a GitHub Security Advisory or issue reference.
- Validate the patch against your allocation, streaming, and check reconciliation test suites.
- Assess CVE eligibility — nomad-0001 fires on every dynamic port allocation.
- Coordinate a disclosure date — we are targeting 90 days from first contact.
Contact: see cover email. This brief is confidential until coordinated disclosure.