2.4 KiB
Consul — CWE-407 Disclosure Brief
2026-03-27 · Patch available — awaiting upstream merge
Finding
One O(n²) defect in Consul's service health evaluation. ExcludeBasedOnChecks() uses slices.Contains(IgnoreCheckIDs) for each service health check, causing O(checks×IDs) overhead per service health evaluation. Patch ready for upstream review.
The Defects
consul-0001 (PATCHED — HIGH): agent/structs/structs.go:2244
// Inside ExcludeBasedOnChecks() — per service health eval:
for _, checkID := range s.IgnoreCheckIDs {
if slices.Contains(s.IgnoreCheckIDs, check.CheckID) {
// O(checks×IDs) per health evaluation
}
}
slices.Contains(IgnoreCheckIDs) performs O(IDs) scan for each of N health checks. For N checks and I ignored check IDs: O(N × I) per service health evaluation. Measured ratio: 100×.
Complexity Proof
For N=100 checks, I=100 ignored IDs:
- O(N×I) = 10,000 comparisons per health eval
- Fixed:
map[types.CheckID]bool→ O(N + I) - 100× measured ratio.
Impact
All Consul deployments using IgnoreCheckIDs in service definitions — a common pattern for ignoring maintenance-mode checks. Consul is a widely deployed service mesh and service discovery platform. Service health evaluations run continuously during health check reconciliation. Clusters with many services and many ignored check IDs hit worst case on every health evaluation cycle.
The Fix
Replace slices.Contains(IgnoreCheckIDs) with a pre-built map[types.CheckID]bool:
// Before
if slices.Contains(s.IgnoreCheckIDs, check.CheckID) { ... } // O(IDs)
// After
// CWE-407 fix: map[types.CheckID]bool for O(1) check instead of O(IDs) slices.Contains.
ignoreSet := make(map[types.CheckID]bool, len(s.IgnoreCheckIDs))
for _, id := range s.IgnoreCheckIDs { ignoreSet[id] = true }
if ignoreSet[check.CheckID] { ... }
Patch
defects/consul/patch/consul-0001-excludebasedonchecks-map.patch
What We Ask
- Confirm receipt and assign a GitHub Security Advisory or issue reference.
- Validate the patch against your service health and check evaluation test suite.
- Assess CVE eligibility — fires on every health check evaluation for services with IgnoreCheckIDs.
- Coordinate a disclosure date — we are targeting 90 days from first contact.
Contact: see cover email. This brief is confidential until coordinated disclosure.