Skip to content

Fall back to pip3 when pip is missing; clearer missing-binary error#100

Merged
juangaitanv merged 1 commit into
install-vuln-gatefrom
ivg/u5-pip3-fallback
Jun 11, 2026
Merged

Fall back to pip3 when pip is missing; clearer missing-binary error#100
juangaitanv merged 1 commit into
install-vuln-gatefrom
ivg/u5-pip3-fallback

Conversation

@juangaitanv

Copy link
Copy Markdown
Contributor

Unit 5 of the install-vuln-gate dogfood frictions.

What

  • exec_command resolution now goes through a resolve_binary helper: when which::which("pip") fails it retries pip3 (pip is the one manager with a conventional alias). All exec paths inherit it — install, passthrough subcommands, and the empty-cmd case.
  • Missing-binary error names the binary and the fallback tried:
    • pip: error: 'pip' not found on PATH (also tried 'pip3')
    • others: error: 'npm' not found on PATH
  • Exit 127 unchanged. should_block_install untouched.
  • The post-resolution exec-failure message now prints the resolved path, so it stays accurate when the pip3 fallback was taken.

Tests

New hermetic e2e suite tests/cli_exec_fallback.rs (fake-PM-on-controlled-PATH pattern from cli_install.rs):

  • PATH with only a fake pip3corgea pip install oldpkg==1.0.0 runs it with forwarded args (exit 0).
  • Same for a non-install passthrough (corgea pip list).
  • PATH with neither → exit 127 + the exact message above, nothing executed.
  • corgea npm list with empty PATH → exit 127, error names npm, no fallback hint.

./harness check green (clippy strict, fmt, 256 tests, deps skill).

Known follow-up (out of unit scope)

src/precheck/tree.rs::resolve_pip_tree does its own which::which("pip") without the pip3 fallback, so with a token on a pip3-only system the tree pass degrades to named-only (with its loud warning) even though the install itself runs via pip3. Worth routing through the same resolver in a tree-pass unit.

When `which::which("pip")` fails, exec resolution retries `pip3` — pip
is the one manager with a conventional alias. The missing-binary error
now names the binary and the fallback tried:

    error: 'pip' not found on PATH (also tried 'pip3')

Exit 127 unchanged. The post-resolution exec-failure message names the
resolved path instead of the requested binary so it stays accurate when
the fallback was taken.

New hermetic e2e suite (tests/cli_exec_fallback.rs): a controlled PATH
with only a fake pip3 runs the install through it; a PATH with neither
exits 127 with the message; npm's error names the binary without a
fallback hint.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking finding below. This PR should not merge until the pip fallback is applied consistently to the verification path as well as the final exec path.

Open in Web View Automation 

Sent by Cursor Automation: pr-flow

Comment thread src/precheck/mod.rs
return Ok(p);
}
if binary == "pip" {
if let Ok(p) = which::which("pip3") {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pip3 fallback is only applied to final execution, not to the token-enabled tree verifier. With a Corgea token present, run_parsed_install calls tree::resolve_tree before this exec closure; for pip that path still calls resolve_pip_tree(manager.binary_name(), ...), and src/precheck/tree.rs:49-51 does a direct which::which("pip"). On a system with only pip3, the tree pass returns NamedOnly (pip not found on PATH) and then this new fallback still runs the real install via pip3. For pip install -r requirements.txt, covers_input is true because of the requirements file, but parsed.targets can be empty, so the result is an install that proceeds with no requirement contents or transitives verified. Before this PR, the same host failed closed at exec because pip was missing.

Concrete fix: centralize package-manager binary resolution and use the same pip -> pip3 fallback in tree::resolve_pip_tree before running the dry-run. Add an e2e test with a token/verdict stub, a controlled PATH containing only fake pip3, and corgea pip install -r requirements.txt; assert the dry-run uses pip3 and the tree verdicts are enforced instead of degrading to named-only.

@juangaitanv juangaitanv merged commit 9793e4b into install-vuln-gate Jun 11, 2026
17 checks passed
@juangaitanv juangaitanv deleted the ivg/u5-pip3-fallback branch June 11, 2026 07:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant