Advisory Database
  • Advisories
  • Dependency Scanning
  1. pypi
  2. ›
  3. GitPython
  4. ›
  5. GHSA-956x-8gvw-wg5v

GHSA-956x-8gvw-wg5v: GitPython: command injection via unguarded Git options in `Repo.archive()`, `git.ls_remote()`, and arbitrary file overwrite via `Repo.iter_commits()` / `Repo.blame()`

July 21, 2026

GitPython spawns the real git binary with an argument vector built from caller-supplied values. To prevent argument injection, GitPython maintains denylists of “unsafe” Git options (--upload-pack, --receive-pack, --exec, -c, --config, …) that can be abused to run arbitrary commands, and enforces them with Git.check_unsafe_options().

That enforcement is only wired into the network commands — clone_from, Remote.fetch, Remote.pull, Remote.push. Several other public APIs that also forward caller-controlled values into the git argv have no guard at all:

  1. Repo.archive(ostream, treeish=None, prefix=None, **kwargs) forwards **kwargs verbatim into git archive. An attacker-influenced options mapping such as {"remote": ".", "exec": "<cmd>"} becomes git archive --remote=. --exec=<cmd> -- <treeish>, and git archive --remote=<local repo> invokes git-upload-archive whose path is overridden by --exec → arbitrary command execution under default Git configuration (no protocol.ext.allow needed).

  2. repo.git.ls_remote(<url>, upload_pack="<cmd>") (and the dynamic-command builder generally) turns the upload_pack kwarg into --upload-pack=<cmd> with no guard → arbitrary command execution.

  3. Repo.iter_commits(rev) and Repo.blame(rev, file) place the caller’s rev value into the argv before the -- end-of-options separator and apply no leading-dash check. A benign-looking ref value such as --output=/path/to/file is parsed by git rev-list / git blame as the --output option, which opens and truncates an arbitrary file before Git even validates the revision → arbitrary file clobber (integrity/availability; can destroy keys, configs, lockfiles, or be aimed at files the host later sources).

The first two are direct code execution; the third is an arbitrary file-overwrite primitive. All share one root cause: the check_unsafe_options / end-of-options discipline that GitPython applies to clone/fetch/pull/push was never extended to these sinks.

References

  • github.com/advisories/GHSA-956x-8gvw-wg5v
  • github.com/gitpython-developers/GitPython/commit/701ce32fe5ba8cb622c0e0342a376a6beb47d738
  • github.com/gitpython-developers/GitPython/pull/2163
  • github.com/gitpython-developers/GitPython/releases/tag/3.1.51
  • github.com/gitpython-developers/GitPython/security/advisories/GHSA-956x-8gvw-wg5v

Code Behaviors & Features

Detect and mitigate GHSA-956x-8gvw-wg5v with GitLab Dependency Scanning

Secure your software supply chain by verifying that all open source dependencies used in your projects contain no disclosed vulnerabilities. Learn more about Dependency Scanning →

Affected versions

All versions before 3.1.51

Fixed versions

  • 3.1.51

Solution

Upgrade to version 3.1.51 or above.

Impact 8.4 HIGH

CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Learn more about CVSS

Weakness

  • CWE-77: Improper Neutralization of Special Elements used in a Command ('Command Injection')
  • CWE-88: Improper Neutralization of Argument Delimiters in a Command ('Argument Injection')

Source file

pypi/GitPython/GHSA-956x-8gvw-wg5v.yml

Spotted a mistake? Edit the file on GitLab.

  • Site Repo
  • About GitLab
  • Terms
  • Privacy Statement
  • Contact

Page generated Sat, 08 Aug 2026 00:17:16 +0000.