# 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`

```go
// 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`

```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`

```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`

```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`:

```go
// 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

1. Confirm receipt and assign a GitHub Security Advisory or issue reference.
2. Validate the patch against your allocation, streaming, and check reconciliation test suites.
3. Assess CVE eligibility — nomad-0001 fires on every dynamic port allocation.
4. Coordinate a disclosure date — we are targeting 90 days from first contact.

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