1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use Path;
/// Priority score for a resolved candidate path: `.exe` beats `.com` beats
/// `.cmd` beats `.bat` beats any other extension beats no extension.
///
/// This function is cross-platform so that `select_path_candidate` can be
/// exercised on Linux CI without requiring a Windows runner. The extension
/// values are Windows-specific, but the comparison logic is pure Rust.
///
/// On non-Windows builds the function is not called from production code
/// (only from tests) — the `allow(dead_code)` suppresses the resulting lint.
pub
/// Pure selection function: given a list of fully-resolved candidate paths and
/// the current working directory, return the best candidate that is **not**
/// located under `cwd`, applying `candidate_priority` to break ties.
///
/// This function is extracted for unit-testability: callers inject arbitrary
/// candidate lists and CWD values so the security invariant can be verified
/// without touching the real file system or environment. Being cross-platform
/// also lets the ripr quality gate observe call paths on Linux CI runners.
///
/// ## Security invariant (two layers of defense)
///
/// 1. **Absolute-only**: any candidate that is not an absolute path is dropped
/// immediately. A relative candidate (e.g. produced by an empty `;;` PATH
/// entry via `dir.join`) resolves against the CWD and is indistinguishable
/// from a planted binary. This is the primary guard against the
/// empty-PATH-entry bypass.
/// 2. **CWD exclusion**: candidates whose parent directory canonicalizes to `cwd`
/// are dropped. If canonicalize fails (non-existent dir in a unit test)
/// the raw path is compared instead — production candidates always come from
/// real `.is_file()`-verified PATH dirs where canonicalize succeeds.
///
/// Returns `None` when every candidate is filtered out or when `candidates` is
/// empty (tool genuinely not on PATH; better than running a planted binary).
///
/// On non-Windows builds the function is not called from production code
/// (only from tests) — the `allow(dead_code)` suppresses the resulting lint.
pub