GitPython: Unsafe git option guard bypass via split_single_char_options=False short-option token smuggling enables command execution
Summary
The check_unsafe_options guard can be bypassed on every guarded method (clone/clone_from, fetch/pull/push, ls_remote, iter_commits, blame, archive) by combining a single-character kwarg with split_single_char_options=False. The guard's candidate list omits the smuggled option, but transform_kwarg emits a JOINED -n<value> argv token that git parses as --upload-pack=<cmd>, yielding arbitrary command execution at the default allow_unsafe_options=False. This is an incomplete-fix bypass of commit e8d0fbf7 (the fix for GHSA-r9mr-m37c-5fr3), which only emits value-derived candidates when split_single_char_options is True.
Root Cause
_option_candidates derives value-token candidates only under if len(key)==1 and split_single_char_options: (cmd.py:1048, added by e8d0fbf7). With split_single_char_options=False, _option_candidates([], {"n":"utouch <cmd>;git-upload-pack"}) returns only ['-n'] (not on the denylist), so the guard passes. But transform_kwarg('n', value, split_single_char_options=False) emits the JOINED token -nutouch <cmd>;git-upload-pack (cmd.py:1631). git clusters value-less short flags then parses -u<cmd> = --upload-pack=<cmd> → command execution. The hardened guard WOULD block the joined token if it saw it — the flaw is it never receives it.
Impact
Arbitrary OS command execution as the host process (via --upload-pack) at default allow_unsafe_options=False, affecting all guarded methods that forward kwargs. Precondition: the app forwards a user-controlled kwargs dict containing split_single_char_options=False plus a single-char key (same user-dict-forwarding model GHSA-r9mr-m37c-5fr3 accepts).
Proof of Concept
from git import Repo
Repo.clone_from(src, dst,
n="utouch /tmp/ACE;git-upload-pack",
split_single_char_options=False) # /tmp/ACE created -> ACE
Attack Chain
- Entry: app forwards user kwargs to
Repo.clone_from(url, path, **kwargs):{split_single_char_options: False, n: 'utouch /tmp/ACE;git-upload-pack'}. - Check:
check_unsafe_options(_option_candidates([], kwargs), unsafe_git_clone_options). Guard: denylist includes--upload-pack/-u. Bypass proof:_option_candidatesyields only['-n'](value token skipped becausesplit=False); guard never sees-u. - Sink:
transform_kwargemits joined token (cmd.py:1631). argv (observed):['git','clone','-v','-nutouch /tmp/ACE;git-upload-pack','--','<src>','<dst>']. - Impact: git clusters
-n+-u<cmd>→ runs upload-pack command → ACE.
Bypass Evidence
Independently reproduced (gate harness, default allow_unsafe_options=False): the split=False payload created the marker VH05_GATE_ACE (ACE); the clone returned normally (guard bypassed). Control: n='--upload-pack=…' (split default True) → UnsafeOptionError: --upload-pack is not allowed. Fix-commit read: e8d0fbf7 extends candidates only under if len(key)==1 and split_single_char_options: — split=False skips value emission. Also confirmed the earlier clustering-parse fix (commit 56806080) does not cover this because the guard only ever receives ['-n'].
Affected Versions
GitPython <= 3.1.57 (code present verbatim on the latest release tag).
Suggested Fix
Make _option_candidates emit value-derived candidates regardless of split_single_char_options (i.e. also for the joined -n<value> form), OR run check_unsafe_options over the fully-transformed argv rather than the reconstructed name-only candidate list.
Reported by zx (Jace) — GitHub: @manus-use
Software afectado
Haz clic en una tecnología para ver todas sus vulnerabilidades.
| Plataforma | Paquete | Versiones vulnerables | Corregida en |
|---|---|---|---|
| Python (PyPI) | gitpython | < 3.1.58 | 3.1.58 |
Referencias
- https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-wvpp-8hx9-p66j
- https://nvd.nist.gov/vuln/detail/CVE-2026-76220
- https://github.com/gitpython-developers/GitPython/pull/2204
- https://github.com/gitpython-developers/GitPython/commit/96a888f4d782cb2f80452148e48e60ce4af6d541
- https://github.com/gitpython-developers/GitPython
- https://github.com/gitpython-developers/GitPython/releases/tag/3.1.58
- https://www.vulncheck.com/advisories/gitpython-before-command-execution-via-split-single-char-options
- https://pypi.org/project/gitpython
- https://github.com/advisories/GHSA-wvpp-8hx9-p66j
- Vector CVSS
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H- Debilidad (CWE)
CWE-88- Plataforma
- Python (PyPI)
- Paquete
gitpython- Publicada
- 07.08.2026
- Actualizado
- 11.10.2026 15:18
Fuentes y licencias
OSV / GitHub Advisory Database - PYSEC-2026-3843 - PyPA Advisory Database; CC BY 4.0
OSV / GitHub Advisory Database - GHSA-wvpp-8hx9-p66j - CC BY 4.0
Historial de vulnerabilidades: gitpython
Todas las vulnerabilidades publicadas de este paquete (Python (PyPI)), de la más reciente a la más antigua. Muestra si es un fallo aislado o un paquete que hay que vigilar.
- Entradas en total
- 37
- Primera → última
- 12.2022 09.2026
- Sin corrección
- 0
- Explotada en ataques
- 0
Distribución por gravedad
- Crítica 3
- Alta 26
- Media 8
Divulgaciones por año
- 2022: 1
- 2023: 3
- 2024: 1
- 2025: 0
- 2026: 32
-
GitPython: Unsafe git option guard bypass via split_single_char_options=False short-option token smuggling enables command execution esta entrada
Identifica las vulnerabilidades de tu aplicación
Con la integración de DockRay y el inventario de software activado, DockRay compara las versiones notificadas de los componentes con las vulnerabilidades conocidas y avisa de las coincidencias confirmadas. La cobertura depende de la tecnología compatible y de los avisos disponibles.