{"id":"GHSA-4gmw-gg2m-w46p","title":"GitPython: Unguarded git read-tree option forwarding in IndexFile.from_tree/reset/merge_tree enables arbitrary file overwrite","summary":"GitPython: Unguarded git read-tree option forwarding in IndexFile.from_tree/reset/merge_tree enables arbitrary file overwrite","severity":"high","cvss":8.1,"cwe":["CWE-88"],"vendor":"GitPython","product":"GitPython","ecosystem":"pip","affected":["GitPython <= 3.1.57"],"patched":["GitPython 3.1.58"],"published":"2026-08-07","updated":"2026-08-07","source":"GHSA","sourceUrl":"https://github.com/advisories/GHSA-4gmw-gg2m-w46p","references":[{"url":"https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-4gmw-gg2m-w46p"},{"url":"https://github.com/gitpython-developers/GitPython/pull/2204"},{"url":"https://github.com/gitpython-developers/GitPython/commit/9b5dcaf85da5946dbf69dcd53f9edba08f760b32"},{"url":"https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58"},{"url":"https://github.com/advisories/GHSA-4gmw-gg2m-w46p"}],"tags":["ghsa","pip"],"ingestedAt":"2026-08-07T16:14:42.484Z","slug":"GHSA-4gmw-gg2m-w46p","body":"## Overview\n\n## Summary\n`IndexFile.from_tree`, `IndexFile.reset` (→ from_tree) and `IndexFile.merge_tree` append caller-influenced treeish strings positionally to `git read-tree` with no unsafe-option guard, no `allow_unsafe_options` parameter, and no `--` separator. `git read-tree --index-output=<file>` writes the resulting index to an arbitrary path, and last-occurrence-wins lets an injected `--index-output` override the method's internal temp path — clobbering an arbitrary file with a valid git-index blob. This is a distinct, never-guarded sink: commit `3af0c251` (GHSA-3f7w-8rr8-f37f) guarded only `checkout_index` and `tag`; `read_tree` was left unprotected (it is among the acknowledged unguarded call sites in that advisory's sweep but was never reported or fixed).\n\n## Root Cause\n`from_tree` (index/base.py:388), `reset` (delegates to from_tree), and `merge_tree` (index/base.py:291) call `repo.git.read_tree(*arg_list)` with no `check_unsafe_options` and no `--`. The treeish is caller-influenced and positional.\n\n## Impact\nArbitrary file overwrite / destruction at the privileges of the host process. Content is constrained to a git-index blob (not attacker-chosen, so not RCE), but the target path is fully attacker-controlled — corrupting/truncating configs or destroying files at attacker-chosen writable locations = I:H + A:H (per the skill's \"overwrite-any-path = I:H\" rule). Pure VALUE control (positional treeish). Default configuration.\n\n## Proof of Concept\n```python\nIndexFile.from_tree(repo, \"--index-output=/home/victim/.bashrc\")\n# target overwritten with a valid git-index blob (DIRC...)\n```\n\n## Attack Chain\n1. Entry: app calls `IndexFile.from_tree(repo, treeish)` / `reset(commit=…)` / `merge_tree(base=…, rhs=…)` with attacker `treeish=\"--index-output=/home/victim/.bashrc\"`.\n2. Check: NONE — the methods have no `allow_unsafe_options` and never call `check_unsafe_options`.\n3. Sink: `repo.git.read_tree(*arg_list)` — no `--`. argv (from_tree, observed): `['git','read-tree','--index-output=<tmp>','--index-output=/…/victim']` (last-wins).\n4. Impact: target path created/overwritten with a valid git-index blob; existing content destroyed.\n\n## Bypass Evidence\nIndependently reproduced (gate harness): `IndexFile.from_tree(repo,'--index-output=<victim>')` → victim overwritten; before=`IMPORTANT ORIGINAL CONTENT`, after starts `DIRC\\x00\\x00\\x00\\x02…` (destructive clobber, valid index blob). `reset(commit=…)` and both `merge_tree` positionals verified. Fix-commit read: `3af0c251` touched only `checkout_index`+`tag`; `read_tree` untouched on HEAD.\n\n## Affected Versions\n`GitPython <= 3.1.57` (sinks present verbatim on the latest release tag).\n\n## Suggested Fix\nAdd a `check_unsafe_options` guard (with an `allow_unsafe_options` parameter) to `from_tree`/`reset`/`merge_tree`, and/or place a `--` separator before the positional treeish arguments; block `--index-output` (a path-taking option) on this sink.\n\n---\nReported by **zx (Jace)** — GitHub: @manus-use\n\n## Affected packages\n\n- `GitPython <= 3.1.57`\n\n## Remediation\n\nUpgrade to a patched release:\n\n- `GitPython 3.1.58`","depth":"twilight","depthScore":45,"depthScoreParts":{"impact":44.6,"likelihood":0,"exploitation":0,"ransomware":0},"changes":[]}