fix(interface): prevent path traversal and argument injection in clone_repository - #1157
fix(interface): prevent path traversal and argument injection in clone_repository#1157Gracy769 wants to merge 2 commits into
Conversation
…e_repository - Replace unsafe Path().stem/name derivation with derive_repo_base_name() which strips .git suffix and sanitizes via regex, preventing '..git' from resolving to '..' and causing rmtree to delete parent directories. - Add resolved-path containment check: clone_path.resolve() must start with temp_dir.resolve(), rejecting any traversal attempt. - Insert '--' end-of-options separator before repo_url in the git clone subprocess call, preventing targets starting with '-' from being interpreted as git flags (e.g. --upload-pack for RCE). - Add explicit validation rejecting repo_url starting with '-' with a clear error message before any subprocess invocation. Fixes usestrix#1133, fixes usestrix#1134.
Greptile SummaryThe PR hardens repository cloning by deriving sanitized clone names, adding a destination-containment check, rejecting dash-prefixed targets, and terminating Git options. However, the containment check still accepts the temporary directory itself, leaving the reported
Confidence Score: 3/5This PR is not safe to merge until the clone destination is required to be a strict descendant of the per-run temporary directory. A fresh scan targeting Files Needing Attention: strix/interface/utils.py
|
| Filename | Overview |
|---|---|
| strix/interface/utils.py | Adds clone-path and Git-argument hardening, but the new containment predicate accepts clone_path == temp_dir, preserving the ..git recursive-deletion vulnerability. |
Prompt To Fix All With AI
### Issue 1
strix/interface/utils.py:1570-1571
**Containment check accepts temp root**
When a fresh scan targets `..git`, `derive_repo_base_name` produces `.`, so `clone_path.resolve()` equals `temp_dir.resolve()` and passes the new prefix check, causing `shutil.rmtree` to delete the per-run directory and its sibling clones. **How this was verified:** The repository-name derivation and fresh-run caller were traced through the containment branch to the recursive-deletion sink.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "fix(interface): prevent path traversal a..." | Re-trigger Greptile
…= temp_dir The previous startswith check accepted clone_path equal to temp_dir itself (a string starts with itself), so '..git' deriving '.' would still resolve to temp_dir and pass through to shutil.rmtree. Now requires clone_path to be a strict descendant: adds equality rejection and uses os.sep-terminated prefix to also prevent sibling directory prefix collisions.
Summary
Fixes #1133 and #1134.
Two security bugs in
clone_repository()(strix/interface/utils.py):Bug 1 — Path traversal via crafted repo URL (#1133)
Before: The repo directory name was derived using
Path(repo_url).stem/.name. A crafted target like..gitcauses.stemto return., makingclone_path = temp_dir / "."resolve totemp_diritself. The subsequentshutil.rmtree(clone_path)then deletes the entire parent temp directory and all sibling clone directories.Fix:
Path().stem/.namederivation withderive_repo_base_name(), which already exists in the codebase, strips.gitsuffixes properly, and sanitizes via regex.clone_path.resolve()must start withtemp_dir.resolve(), rejecting any traversal attempt with a clear error.Bug 2 — Argument injection in git clone (#1134)
Before:
repo_urlwas passed directly as a positional argument togit clonewithout a--end-of-options separator. A target starting with-(e.g.--upload-pack="malicious command") would be interpreted as a git flag, potentially leading to remote code execution on the Strix host.Fix:
--separator beforerepo_urlin the subprocess argument list, so git treats everything after it as positional arguments regardless of leading dashes.repo_urlstarting with-before the subprocess is even invoked, with a clear error message.Changes
strix/interface/utils.py: Modifiedclone_repository()function (+17 lines, -2 lines)Testing
Both attack vectors can be verified: