IndexFile.from_tree/reset/merge_tree enables arbitrary file · GitPython: Unguarded git read-tree option forwarding
Affects cf2tfSource GCVE Database
Not known to be exploited · CVSS 7.2 High : upgrade to 0.9.2_8 soon.
Data as of 26 Oct 2026, 17:16 UTC
- EPSS
- 0.5% chance of exploitation in 30 days – higher than 45% of CVEsExploit Prediction Scoring System: the likelihood attackers will use this flaw soon.
- Patch
- Available – fixed in 0.9.2_8
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:H/SC:N/SI:N/SA:NExploitation evidence
Disclosed: evidence found.
CVE published 19 Aug 2026
Detectable: no evidence on record.
No public nuclei template indexed
Weaponised: no evidence on record.
No public exploit code indexed in Metasploit or Exploit-DB
Exploited in the wildExploited: no evidence on record.
Not in CISA KEV and no source reports exploitation
Observed by OffSeq MirageSeen by Mirage: no evidence on record.
No attack traffic recorded by OffSeq Mirage sensors
A missing step is not evidence of safety. Sources: cve.org (opens in a new tab), the Metasploit, Exploit-DB and nuclei-templates index as of 26 Oct 2026.
What to do
Upgrade cf2tf to 0.9.2_8.
Affected software
| Product | Affected | Fixed in |
|---|---|---|
Homebrewcf2tfpkg:brew/cf2tfOther threats | Affected
| Fixed in
|
Check your own hosts for these packages with threat-finder (opens in a new tab), our free open-source scanner.
Description
## Summary `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). ## Root Cause `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. ## Impact Arbitrary 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. ## Proof of Concept ```python IndexFile.from_tree(repo, "--index-output=/home/victim/.bashrc") # target overwritten with a valid git-index blob (DIRC...) ``` ## Attack Chain 1. Entry: app calls `IndexFile.from_tree(repo, treeish)` / `reset(commit=…)` / `merge_tree(base=…, rhs=…)` with attacker `treeish="--index-output=/home/victim/.bashrc"`. 2. Check: NONE — the methods have no `allow_unsafe_options` and never call `check_unsafe_options`. 3. Sink: `repo.git.read_tree(*arg_list)` — no `--`. argv (from_tree, observed): `['git','read-tree','--index-output=<tmp>','--index-output=/…/victim']` (last-wins). 4. Impact: target path created/overwritten with a valid git-index blob; existing content destroyed. ## Bypass Evidence Independently 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. ## Affected Versions `GitPython <= 3.1.57` (sinks present verbatim on the latest release tag). ## Suggested Fix Add 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.
References
- github.com/gitpython-developers/GitPython/security/advisories/GHSA-4gmw-gg2m-w46p (opens in a new tab)
- nvd.nist.gov/vuln/detail/CVE-2026-76219 (opens in a new tab)
- github.com/gitpython-developers/GitPython/pull/2204 (opens in a new tab)
- github.com/gitpython-developers/GitPython/commit/9b5dcaf85da5946dbf69dcd53f9edba08f760b32 (opens in a new tab)
- github.com/gitpython-developers/GitPython (opens in a new tab)
- github.com/gitpython-developers/GitPython/releases/tag/3.1.58 (opens in a new tab)
- vulncheck.com/advisories/gitpython-before-arbitrary-file-overwrite-via-read-tree (opens in a new tab)