Skip to content

security: harden claude binary resolution#60

Merged
sam-powers merged 1 commit into
mainfrom
security/harden-claude-binary-resolution
Jun 13, 2026
Merged

security: harden claude binary resolution#60
sam-powers merged 1 commit into
mainfrom
security/harden-claude-binary-resolution

Conversation

@sam-powers

Copy link
Copy Markdown
Owner

What

Tightens how the claude CLI path is discovered before it's spawned, so a resolution step can never hand Command::new something that isn't a real executable.

  • The login-shell fallback used an interactive login shell (-lic). Switched to a non-interactive login shell (-lc): we want the profile's PATH, not the side effects of interactive-only rc blocks, and -c keeps it to the single command -v we asked for.
  • The shell-resolved path and the which result are now both gated on .is_file(), matching the rigor the common-install-locations loop already applies. A stray line of shell output can no longer become the spawned binary.

No behavior change for a normally-installed CLI. Rust bar green: cargo fmt --check, cargo clippy -D warnings, cargo test (27).

🤖 Generated with Claude Code

Resolving the `claude` CLI path now validates every result before
handing it to Command::new:

- The login-shell fallback used an interactive login shell (`-lic`).
  Switch to a non-interactive login shell (`-lc`): we want the
  profile's PATH, not the side effects of interactive-only rc blocks.
- The shell-resolved path and the `which` result are now both gated on
  `.is_file()`, matching the rigor the common-install-locations loop
  already applies. A stray line of shell output can no longer become
  the spawned binary.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sam-powers sam-powers merged commit 3c3e83a into main Jun 13, 2026
3 checks passed
@sam-powers sam-powers deleted the security/harden-claude-binary-resolution branch June 13, 2026 21:57
sam-powers added a commit that referenced this pull request Jun 13, 2026
Documents Quill's security posture for a reviewing engineer: the threat
model (deep link as the one attacker-influenced entry point; deserialized
data trusted more than rendered data), the four merged hardening measures
(#57 path confinement + deep-link validation, #58 annotation sanitization,
#59 URL scheme allowlists, #60 binary-resolution hardening), and the two
deliberate non-fixes left in place with rationale (asset-protocol $HOME/**
scope, remote-image beacon).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@sam-powers sam-powers mentioned this pull request Jun 15, 2026
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