GitHub Advisoryadvisory · PyPI
GHSA-9rj7-rf2p-w77r GitPython: Unguarded git option forwarding in Repo.init enables arbitrary command execution via --template clone hooks
HIGH
Official page ↗
- Aliases
- CVE-2026-76218
- Ecosystem
- PyPI
- Packages
- GitPython
- Severity
- High
- CVSS vector
- CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H
- Weaknesses
- CWE-88, CWE-94
- Reviewed
- 2026-08-07
Affected packages
• PyPI GitPython: < 3.1.58 → fixed in 3.1.58
Description
Summary
`Repo.init()` forwards `**kwargs` verbatim to `git init` with no unsafe-option guard and no `allow_unsafe_options` parameter. `git init --template=` copies `/hooks/*` into the new repo's `.git/hooks`, so an attacker-controlled `template` kwarg plants a hook that executes on the next git operation → arbitrary code execution. `--template` is already recognized as unsafe for clone (it is on `unsafe_git_clone_options`, and GHSA-6p8h-3wgx-97gf covers the clone path), but `Repo.init` is a distinct method that never received a guard and needs an independent fix.
Root Cause
`Repo.init(path, mkdir, odbt, expand_vars, kwargs)` is a bare `git.init(kwargs)` (git/repo/base.py:1435) with no `check_unsafe_options` and no `allow_unsafe_options`.
Impact
Arbitrary code execution (hook fires on next git op) at the privileges of the host process. Two preconditions raise attack complexity (AC:H): the app must forward a `template=` kwarg (KEY control) AND the attacker must stage an executable hook directory at a known path — the same profile GHSA-6p8h-3wgx-97gf accepted as HIGH for the clone path. Default `allow_unsafe_options` is irrelevant here because `Repo.init` has no guard at all.
Proof of Concept
```python
attacker stages /evil/hooks/post-commit (executable)
from git import Repo
Repo.init(path, template="/evil")
next commit runs /evil/hooks/post-commit -> ACE
```
Attack Chain
1. Entry: attacker stages `/evil/hooks/post-commit` (executable) and gets the app to call `Repo.init(path, template='/evil')`.
2. Check: NONE on `Repo.init`. Bypass proof: base.py:1435 is a bare `git.init(kwargs)`. argv (observed): `['git','init','--template=/evil']`.
3. Sink: git copies `/evil/hooks/post-commit` → `/.git/hooks/post-commit`.
4. Impact: next commit runs the hook → arbitrary code execution.
Bypass Evidence
Independently reproduced (gate harness): `Repo.init(dst, template='')` → argv `['git','init','--template=']` unguarded; hook copied into `.git/hooks/post-commit`; after `git commit` the `INIT_ACE` marker was created. `--separate-git-dir=` is a parallel arbitrary-redirect vector through the same unguarded sink (value control only).
Affected Versions
`GitPython <= 3.1.57` (unguarded `git.init(kwargs)` present verbatim on the latest release tag).
Suggested Fix
Add a `check_unsafe_options` guard (with an `allow_unsafe_options` parameter) to `Repo.init`, consulting a denylist that includes `--template` and `--separate-git-dir` (path-taking / hook-installing options).
---
Reported by zx (Jace) — GitHub: @manus-use
Related
Alias · CVE (1)
- CVE-2026-76218 GitPython before 3.1.58 contains a remote code execution vulnerability in Repo.init that forwards unsafe git options without validation. vulnerability
References
- https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-9rj7-rf2p-w77r web
- https://nvd.nist.gov/vuln/detail/CVE-2026-76218 advisory
- https://github.com/gitpython-developers/GitPython/pull/2204 web
- https://github.com/gitpython-developers/GitPython/commit/d9ddb55bdc66 web
- https://github.com/gitpython-developers/GitPython package
- https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58 web
- https://www.vulncheck.com/advisories/gitpython-before-remote-code-execution-via-repo-init web