GitPython: Unguarded git option forwarding in IndexFilecheckout() and TagReferencecreate() enables arbitrary file overwrite and arbitrary file read (GHSA-3f7w-8rr8-f37f) (High) -DC-Aug2026-1271

Listen to this Post

GitPython implements a safety mechanism via `Git.check_unsafe_options()` to block dangerous git options, gated per method by an `allow_unsafe_options` parameter. However, this guard is applied on a per‑call‑site basis. Any API that forwards `kwargs` into a git command without explicitly invoking the check passes caller‑controlled options straight to the underlying git binary. A mechanical sweep of every method that forwards `kwargs` into a `.git.(…)` call uncovered 14 unguarded sites. Two of these reach a git option that accepts a filesystem path, enabling practical attacks.
The first instance is `IndexFile.checkout()` → git checkout-index. The method accepts `kwargs` and forwards them without any call to check_unsafe_options(). The `–prefix=` option of `git checkout-index` is prepended to every output path and is not confined to the working tree. An absolute prefix therefore writes tracked file contents anywhere the process can write, and `-f` forces overwrites of existing files. Since both the destination (via prefix) and the content (repository blobs) are attacker‑influenced, an attacker who can land a file in the repository (e.g., via a pull‑request branch, a mirrored repository, or an agent‑cloned repository) can write files such as authorized_keys, .bashrc, or `post-checkout` hooks to achieve code execution as the service account.
The second instance is `TagReference.create()` → git tag. This method also forwards `kwargs` unguarded, and its documentation explicitly advertises the passthrough. `git tag` accepts `-F ` / --file=<file>, which reads the tag message from an arbitrary path. The annotated tag object stores that content, and GitPython returns it to the caller via TagReference.tag.message, so the file contents are returned in‑band. This allows an attacker to read any file readable by the process, without raising any exception.
Both vulnerabilities are still present at HEAD (07e80555, 2026‑07‑25) and in the latest release 3.1.55. The remaining 12 unguarded sites were assessed and deemed either neutralised (e.g., `IndexFile.from_tree()` where GitPython appends its own `–index-output` after the caller’s kwargs, and git honours the last occurrence) or lacking a path‑taking option that could lead to write or disclosure. This defect class has now been fixed four times in four different places (Repo.archive(), Git.ls_remote(), Commit.count(), and the two here), highlighting that the opt‑in guard model leaves every new kwargs‑forwarding API vulnerable until reported. A structural fix would enforce the check centrally in Git._call_process(), consulting a per‑command unsafe‑option table unless the caller explicitly opts out.

DailyCVE Form:

Platform: GitPython
Version: 3.1.55
Vulnerability : Arbitrary file overwrite/read
Severity: High
date: 2026-07-26

Prediction: 2026-08-10

What Undercode Say:

Reproduce arbitrary file overwrite via IndexFile.checkout()
from git import Repo
Repo("/path/to/repo").index.checkout(prefix="/tmp/target_dir/", a=True, f=True)
Reproduce arbitrary file read via TagReference.create()
from git import Repo
from git.refs.tag import TagReference
t = TagReference.create(Repo("/path/to/repo"), "x", force=True, a=True, F="/etc/passwd")
print(t.tag.message)
Sweep all unguarded call sites (poc/sweep.py)
Identifies 14 sites; 2 exploitable, 12 assessed as non-exploitable or neutralised

Exploit:

  • Instance 1 (Overwrite): Supply `prefix=”/absolute/path/”` to IndexFile.checkout(). The content of any tracked file (e.g., a blob named authorized_keys) is written to /absolute/path/authorized_keys, overwriting existing files with -f. This can lead to code execution if the written file is a hook or a configuration file read by privileged processes.
  • Instance 2 (Read): Supply `F=”/etc/passwd”` (or any other file) to TagReference.create(). The file content is embedded in the tag message and returned to the caller, enabling disclosure of sensitive files.

Protection:

  • Immediate: Add `allow_unsafe_options: bool = False` to both `IndexFile.checkout()` and TagReference.create(). Gate `Git._option_candidates(args, kwargs)` against new unsafe‑option lists:
    – `unsafe_git_checkout_index_options = [“–prefix”]` (consider --temp)
    – `unsafe_git_tag_options = [“–file”, “-F”]` (consider -s, -u/--local-user, --cleanup)
  • Structural: Enforce the check centrally in `Git._call_process()` so that every git invocation consults a per‑command unsafe‑option table unless the caller explicitly opts out. This would make new call sites safe by default and close the remaining unguarded sites.

Impact:

  • Arbitrary File Overwrite: An attacker with the ability to inject content into a repository (via PR, mirror, or agent‑clone) can write files outside the working tree with full control over both destination and content. This can lead to remote code execution (e.g., via ~/.ssh/authorized_keys, ~/.bashrc, or .git/hooks/post-checkout) with the privileges of the service account.
  • Arbitrary File Read: An attacker can read any file readable by the process, leading to information disclosure of sensitive system or application files.
  • Risk Rating: High, given the direct path to code execution and the ease of exploitation through attacker‑controlled repository content.

🎯Let’s Practice Exploiting & Learn Patching For Free:

🎓 Live Courses & Certifications:

Join Undercode Academy for Verified Certifications

🚀 Request a Custom Project:

Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top