Skip to content

GHSA-rpm5/GHSA-x2qx - GitPython command injection

Two high-severity GitPython advisories affect applications that let untrusted input shape Git operation options:

  • GHSA-rpm5-65cw-6hj4: unsafe Git option checks can be bypassed with Python kwargs such as upload_pack and receive_pack, which normalize into dangerous Git flags.
  • GHSA-x2qx-6953-8485: multi_options validation happens before shlex.split(), allowing a seemingly safe option string to split into unsafe flags such as --config core.hooksPath=....

For agentic coding systems, CI workers, repository importers, and internal automation bots, the practical risk is code execution on the worker handling repo clone/fetch/pull/push operations.

Affected versions

  • Vulnerable: GitPython >=3.1.30, <3.1.47 for GHSA-rpm5-65cw-6hj4
  • Vulnerable: GitPython <3.1.47 for GHSA-x2qx-6953-8485
  • Fixed: GitPython 3.1.47+

Indicator-of-exposure

  • The repository depends on GitPython directly or transitively.
  • Application code calls Repo.clone_from(), Repo.clone(), Remote.fetch(), Remote.pull(), Remote.push(), or Submodule.update().
  • Users, tenants, webhooks, workflow YAML, job definitions, repository metadata, or LLM/tool inputs can influence kwargs, multi_options, clone_multi_options, or “extra git options.”
  • The process performing Git operations has access to SSH keys, cloud credentials, package publishing tokens, source code, build artifacts, or internal network routes.

Quick checks:

rg -n "GitPython|from git import Repo|import git|Repo\.clone_from|Repo\.clone\(|\.fetch\(|\.pull\(|\.push\(|multi_options|clone_multi_options|upload_pack|receive_pack|allow_unsafe" .
python -m pip show GitPython
pip freeze | rg '^GitPython=='
rg -n "extra.*git|git.*options|clone.*options|repo.*import|repository.*sync|webhook.*clone|workflow.*clone" .

Remediation strategy

  • Upgrade GitPython to 3.1.47+ everywhere this repository controls manifests, lockfiles, images, or runtime packaging.
  • Remove user-controlled pass-through of Git kwargs and multi_options.
  • Replace free-form Git option input with a strict allow-list of product features, represented as typed fields rather than raw flags.
  • Block upload_pack, receive_pack, exec, config, c, core.hooksPath, and any option that can choose helper commands, hooks, config, protocol behavior, or SSH commands.
  • Run repo-ingest workers with least privilege, isolated workspaces, disabled hooks where possible, and credentials scoped to the one repository operation.
  • Review worker logs and credential access if untrusted users could control Git options during the exposure window.

The prompt

Model context: this prompt was generated by GPT 5.5 Extra High reasoning.

You are remediating GitPython command injection advisories
GHSA-rpm5-65cw-6hj4 and GHSA-x2qx-6953-8485. Produce exactly one output:

- A reviewer-ready PR/change request that upgrades GitPython, removes unsafe
  option pass-through, adds regression coverage, and documents operator cleanup,
  or
- TRIAGE.md if this repository does not own an affected GitPython runtime or
  safe patch path.

## Rules

- Scope only GHSA-rpm5-65cw-6hj4 and GHSA-x2qx-6953-8485.
- Treat SSH keys, deploy keys, package tokens, cloud credentials, source code,
  repo URLs, and worker environment values as sensitive.
- Do not execute exploit payloads, helper commands, custom hooks, reverse
  shells, or attacker-controlled Git options.
- Do not keep a free-form "extra Git options" feature for untrusted callers.
- Do not auto-merge.

## Steps

1. Inventory every GitPython dependency controlled by this repository:
   requirements files, pyproject files, lockfiles, constraints, Dockerfiles,
   base images, CI images, worker images, SBOMs, vendored code, and deployment
   manifests.
2. Determine every resolved GitPython version. A target is vulnerable if it
   resolves below `3.1.47`.
3. Search code paths that perform repository operations:
   - `Repo.clone_from()`;
   - `Repo.clone()`;
   - `Remote.fetch()`;
   - `Remote.pull()`;
   - `Remote.push()`;
   - `Submodule.update()`;
   - wrappers around repository import, mirror, sync, CI checkout, or agent
     workspace preparation.
4. Determine whether untrusted input can reach GitPython options:
   request bodies, webhook payloads, tenant settings, workflow YAML, job config,
   LLM/tool arguments, database records, environment variables, or "advanced
   options" fields.
5. If GitPython is absent or only used in non-deployable tooling, stop with
   `TRIAGE.md` explaining what was checked and why the runtime is not exposed.
6. Upgrade GitPython to `3.1.47+` on the smallest compatible release line.
   Regenerate lockfiles, constraints, images, SBOMs, and dependency reports.
7. Remove unsafe option pass-through:
   - do not pass user dictionaries directly as `**kwargs`;
   - do not pass user strings to `multi_options` or `clone_multi_options`;
   - reject `upload_pack`, `receive_pack`, `exec`, `config`, `c`,
     `core.hooksPath`, `GIT_SSH_COMMAND`, and equivalent normalized spellings;
   - represent supported behavior as typed fields, then map to a finite
     allow-list of safe GitPython arguments.
8. Add regression tests that do not execute commands:
   - `upload_pack` and `receive_pack` kwargs from untrusted input are rejected;
   - hyphen, underscore, and mixed-normalization forms are rejected;
   - `multi_options` strings containing embedded unsafe flags are rejected;
   - `clone_multi_options` for submodules uses the same validator;
   - validation happens after parsing/normalization, not only before it.
9. Harden repo-ingest execution where this repo controls it:
   - run workers as unprivileged users;
   - isolate workspaces per job;
   - scrub environment variables before Git operations;
   - scope SSH/deploy keys to the target repo and operation;
   - disable Git hooks or run with safe hook policy where supported.
10. Add a PR body section named `GitPython advisory operator actions` that
    states:
    - affected GitPython versions before and after the change;
    - which repo-operation paths were reachable by untrusted input;
    - whether free-form Git option features were removed or restricted;
    - which worker credentials should be rotated if exposure existed;
    - which logs should be reviewed for suspicious helper, hook, config, or SSH
      command options.
11. Run relevant validation: dependency install, unit tests, integration tests
    for repository import/sync, lint/typecheck, image build, SBOM refresh, and
    dependency/security scans available in this repository.
12. Use PR title:
    `fix(sec): remediate GitPython command injection advisories`.

## Stop conditions

- No deployable GitPython runtime is controlled by this repository.
- A fixed GitPython version cannot be consumed without a broader platform
  migration.
- Product requirements depend on arbitrary caller-controlled Git options;
  document the risk and require a product/security decision.
- Verification would require executing attacker-controlled hooks or helper
  commands.
- Validation fails for unrelated pre-existing reasons; document those failures
  instead of broadening scope.

Verification - what the reviewer looks for

  • No controlled lockfile, image, SBOM, or deployment target resolves GitPython below 3.1.47.
  • User-controlled dictionaries, strings, workflow fields, or LLM/tool arguments cannot become raw GitPython kwargs, multi_options, or clone_multi_options.
  • Regression tests cover normalized option names and post-parse validation.
  • Repo-ingest workers do not run with broad credentials or reusable shared workspaces.
  • The PR identifies whether credential rotation and log review are required.

Watch for

  • Updating application requirements while CI, worker, or agent images still carry an older GitPython version.
  • Blocking only literal --upload-pack while allowing upload_pack.
  • Validating multi_options before splitting or normalization.
  • Treating repository URLs as the only untrusted input and missing workflow fields that configure clone/fetch behavior.

References