Skip to content

fix: reject unsafe self-upgrade installer paths - #5172

Merged
mnriem merged 5 commits into
github:mainfrom
mnriem:mnriem-fix-installer-search-hijack
Oct 29, 2026
Merged

mnriem merged 5 commits into
github:mainfrom
mnriem:mnriem-fix-installer-search-hijack

Conversation

@mnriem

@mnriem mnriem commented Oct 29, 2026

Copy link
Copy Markdown
Collaborator

Description

Require absolute installer paths that do not resolve to executables in the current working directory when selecting uv or pipx for install-method probes and self-upgrades. Reject unsafe lookup results without falling back to bare commands.

Add regression coverage for relative paths, working-directory executables, symlinks, valid installed tools, and CLI failure behavior.

Testing

  • Tested locally with uv run specify --help
  • Ran existing tests with uv sync && uv run pytest
  • Tested with a sample project (if applicable)

The full suite was run using the documented worktree-local interpreter rather than the generic command above:

  • uv sync --extra test — passed.
  • LC_ALL=en_US.UTF-8 .venv/bin/python -m pytest tests -q — passed: 13,088 passed, 130 skipped.
  • uv run specify --help — passed.

Run on macOS; Windows-only tests were skipped locally. Sample-project testing is not applicable because this change does not affect scaffolding or slash commands.

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (fill in the disclosure below)

AI disclosure: GitHub Copilot using GPT-6.1 Sol in autonomous mode generated the code and tests, ran validation, and drafted this pull request.

Reject relative and working-directory installer lookup results before registry probes and self-upgrades, including symlinks to working-directory executables.

Assisted-by: GitHub Copilot (model: GPT-6.1 Sol, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI auto review requested due to automatic review settings October 29, 2026 12:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Installer validation still allows working-directory PATH entries to execute project-controlled code during probes or upgrades, leaving a critical security issue unresolved.

2 open issues
What changed in this PR

Introduces installer-path validation for Specify CLI’s detection probes and self-upgrades to prevent execution of working-directory tools.

Changes:

  • Centralizes uv and pipx lookup validation, rejecting unsafe results without falling back to bare commands.
  • Adds path-safety and CLI-failure regression tests, and updates existing mocks to use absolute executable paths.

Validation used isolated standard-library checks; the full suite and macOS/Windows-specific cases were not rerun.

AI review for the requester: GitHub Copilot (model unknown; autonomous; code inspection and isolated checks).

File Description
tests/​specify_cli/​test_version_verification.py Uses absolute installer mocks in upgrade-verification tests.
tests/​specify_cli/​test_version_execution.py Updates installer mocks in execution and failure tests.
tests/​specify_cli/​test_version_detection.py Adds installer-path safety cases and updates lookup expectations.
tests/​specify_cli/​selfs/​test_command_upgrade.py Tests unsafe lookup rejection and updates command mocks.
src/​specify_cli/​_version.py Adds shared installer-path validation for probes and upgrade commands.

Review effort: Max (auto)

Comment thread src/specify_cli/_version.py Outdated
Comment thread src/specify_cli/_version.py Outdated
Compare both lookup and resolved target directories by filesystem identity, rejecting path-validation errors. Preserve rejection details for registry probes, upgrades, and dry runs without masking unrelated missing installers.

Assisted-by: GitHub Copilot (model: GPT-6.1 Sol, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI auto review requested due to automatic review settings October 29, 2026 12:42
@mnriem

mnriem commented Oct 29, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed both findings in 8970a703: installer validation now uses filesystem identity for the lookup and resolved target directories and rejects path-validation errors. Rejected installers retain actionable PATH/working-directory guidance in normal and dry-run output, including failed ownership probes. Added regressions for both uv and pipx; focused automated coverage passed (256 passed, 3 skipped). The full suite was not rerun for this follow-up. Posted on behalf of @mnriem by GitHub Copilot (GPT-6.1 Sol, autonomous mode); implementation, test generation/execution, and this summary were AI-generated.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Windows upgrade tests fail before the CLI runs because decoy files collide with fixture directories, and installer-rejection guidance omits the workaround for implicit current-directory matches.

3 open issues
1 resolved since last review

Review effort: Max (auto)

Comment thread tests/specify_cli/selfs/test_command_upgrade.py Outdated
Comment thread src/specify_cli/_version.py Outdated
@mnriem mnriem added the triage-must-have Verdict: high-value, important work for Spec Kit — do first label Oct 29, 2026
Keep decoy executables in a separate working directory from installer fixtures and exercise the Windows directory layout on all platforms. Explain how to avoid implicit current-directory matches when installer lookup returns a relative path.

Assisted-by: GitHub Copilot (model: GPT-6.1 Sol, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI auto review requested due to automatic review settings October 29, 2026 13:33
@mnriem

mnriem commented Oct 29, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed this round in f5c30633: decoy files now live in a separate project working directory, and the test creates the Windows-shaped installer directories on every platform to guard against collisions. Relative-path rejection guidance now covers implicit Windows current-directory matches in both normal and dry-run output, including ownership probes. The focused command/detection suite passed (122 passed, 3 skipped) on macOS; native Windows validation and the full suite were not rerun for this follow-up. Posted on behalf of @mnriem by GitHub Copilot (GPT-6.1 Sol, autonomous mode); implementation, test generation/execution, and this summary were AI-generated.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

When both installers own specify-cli, a rejected Tier-3 probe can select the other installer instead of returning UNSUPPORTED, risking an upgrade of the wrong installation.

No open issues 🎉

1 previously missed issue

In code that hasn't changed since last review

Medium severity Reject ambiguous installer selection when a probe is rejected

src/​specify_cli/​_version.py:659

When both installers own specify-cli, rejecting one Tier-3 lookup leaves its match false, so this path selects the other installer instead of returning UNSUPPORTED. This can upgrade the wrong installation and occurs symmetrically for uv and pipx. Require no rejected probes before accepting exactly_one_match, and update test_rejected_probe_does_not_hide_a_different_missing_installer accordingly.

3 resolved since last review

Review effort: Max (auto)

Merge upstream main without rewriting PR history. Use the existing uv-tool entrypoint fixture in authentication-failure command tests instead of mocking the detector's old enum-only return shape.

Assisted-by: GitHub Copilot (model: GPT-6.1 Sol, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI auto review requested due to automatic review settings October 29, 2026 13:53
Treat rejected Tier-3 probes as unresolved ownership rather than selecting the other installer. Cover both installer directions and normal/dry-run CLI behavior without invoking an upgrade.

Assisted-by: GitHub Copilot (model: GPT-6.1 Sol, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@mnriem

mnriem commented Oct 29, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed the previously missed ownership ambiguity in 8b85bf7e: Tier-3 detection now remains unsupported when either installer probe is rejected, even if the other registry reports ownership. Symmetric regressions cover both installers and normal/dry-run commands, asserting that no upgrade runs. Authentication/version/self command coverage passed (595 passed, 3 skipped), and Ruff passed. This finding was in the review body only, with no inline conversation; all four existing conversations were already resolved. Posted on behalf of @mnriem by GitHub Copilot (GPT-6.1 Sol, autonomous mode); implementation, test generation/execution, and this summary were AI-generated.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

A critical installer-detection flaw can select the wrong package manager after a probe is rejected, causing self-upgrade to modify the wrong installation.

1 open issue

Review effort: Max (auto)

Comment thread src/specify_cli/_version.py
Copilot AI auto review requested due to automatic review settings October 29, 2026 14:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

This security-sensitive fix depends on Windows executable-search and filesystem-identity behavior, but the supplied macOS-only validation skipped Windows regressions, leaving native Windows confirmation necessary.

No open issues 🎉

1 resolved since last review

Review effort: Max (auto)

@mnriem
mnriem merged commit e7f44e2 into github:main Oct 29, 2026
16 checks passed
@mnriem
mnriem deleted the mnriem-fix-installer-search-hijack branch October 29, 2026 14:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

triage-must-have Verdict: high-value, important work for Spec Kit — do first

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants