## Diamond Recursion Scan — CLEAN

**Scan date:** 2026-03-29
**Pattern:** Recursive cycle/dependency check without visited set (CWE-407 diamond recursion, O(2^D))

### Files examined

- `src/pip/_internal/resolution/resolvelib/resolver.py` — `get_topological_weights`, `visit`
- `src/pip/_internal/resolution/legacy/resolver.py` — `get_installation_order`, `schedule`
- `src/pip/_internal/resolution/resolvelib/candidates.py` — `iter_dependencies`

### Findings

**legacy resolver schedule():** `ordered_reqs.add(req)` is called BEFORE the recursive call into dependencies. This means any node that is already scheduled (in the set) returns immediately on the next visit. The set check is O(1). No diamond blowup. CLEAN.

**resolvelib get_topological_weights / visit():** Uses a `path` set (not list) to guard against cycle re-entry — `if node in path: return`. Additionally limits each node to 5 visits via `len(cur_weights) >= 5`. The 5-visit limit was added as a guard (issue #10557) to prevent O(2^D) blowup on pathologically connected graphs. The underlying pattern was the diamond recursion defect; the fix is a band-aid that caps visits at 5 per node, making it O(5N) = O(N). Current code is effectively mitigated.

Note: `pip-0001` covers a pre-existing CWE-407 defect in the legacy resolver's cache support index.

### Verdict: CLEAN — no unmitigated diamond recursion CWE-407 found
