GitPython 3.1.54 fixes three option-injection paths to RCE and file overwrite
CVE-2026-73623–73625 bypass option controls through templates, diff output and kwarg value smuggling. We examine the fixes and CI exposure.
- AUTHOR
- Karol Rapacz / Breachroad CEO · OSCP · PNPT
- PUBLISHED
- 13 August 2026
- READING TIME
- 14 min read
- TOPIC
- Supply Chain Security
Three GitPython records—CVE-2026-73623, CVE-2026-73624 and CVE-2026-73625—were published on 13 August 2026. All releases through 3.1.53 are affected, and GitPython 3.1.54 contains the fixes. Two paths can execute operating-system commands, while the third can overwrite a file accessible to the process. Their shared cause is not cryptography or repository parsing, but incomplete separation between application values and command-line options interpreted by git.
This matters to CI/CD systems, repository bots, source-analysis platforms, preview services and AI agents using Git libraries. When an application forwards a user-controlled value as a kwarg, revision, clone option or diff argument, text can become a flag for the Git process. Default allow_unsafe_options=False was meant to prevent that, but three independent paths exposed the limits of denylists and pre-transformation argument checks.
CVE-2026-73623: a template installs a clone hook
GHSA-6p8h-3wgx-97gf describes the absence of --template from unsafe_git_clone_options. Git can initialise a repository from a template directory. That directory may include hooks, and post-checkout runs during clone. If an attacker controls the template option and can point to a directory containing a prepared executable hook, command execution follows.
The issue scores 7.5 under CVSS 3.1 with high complexity because it requires a second condition: a readable directory with the hook. A shared filesystem, upload area, temporary directory or network path may satisfy it. A malicious repository URL alone is not always sufficient. Lack of a local account does not eliminate the precondition because web applications commonly allow file placement through another workflow step.
The fix rejects --template and tests direct and keyword forms. The durable lesson is that a security boundary should not depend on a hand-maintained list of a few “bad” options for a much richer program. If an application does not need arbitrary clone switches, expose a narrow business model rather than forwarding a dictionary to Git.
CVE-2026-73624: diff writes to an attacker-chosen path
GHSA-fjr4-x663-mwxc affects Diffable.diff(), mixed into Commit, Tree, IndexFile and Submodule. The method forwarded kwargs without checking unsafe options. Git supports --output=<path>, so an attacker controlling an option name could make the process open and overwrite a chosen file with diff data.
A second route was less obvious. The other value, expected to be a revision, entered argv before the -- separator. A value shaped like an option could therefore become --output even when the attacker did not control a kwarg name. The flaw scores 8.1: the attacker selects the path and may corrupt configuration, authorization material, a lockfile or something executed later.
This is not a fully arbitrary byte write because content comes from a diff. It still compromises integrity and availability and can support another chain in the right context. The fix validates unsafe options before revision parsing and Git invocation, adding regression tests for commit and index diffs.
CVE-2026-73625: safe key, dangerous value
The highest-scored issue, GHSA-r9mr-m37c-5fr3, carries an 8.8. check_unsafe_options built candidates from keyword names. For a one-character key such as n, it saw only -n. A later transformation split key and value into separate argv entries. When the value began with a dangerous long option, Git interpreted that second token independently.
This allowed smuggling --upload-pack, which controls a program Git launches during remote operations. The condition affected clone, fetch, pull, push, ls_remote, iter_commits, blame and archive. A directly named unsafe option was blocked, while the equivalent capability passed through the value of an apparently safe short flag.
The patch evaluates the transformed tokens, including dash-prefixed values. This pattern applies to every CLI wrapper: validation has to inspect the final argv received by the process rather than an earlier object structure. A safe key does not make its value safe when another layer later changes token boundaries.
Establishing actual exposure
Finding GitPython in an image does not prove remote RCE. Determine whether a user controls options, revisions, clone configuration or a diff object; whether the application executes that operation; and which rights the process holds. A service accepting only an approved URL and code-selected directory has less exposure than “Git as a service” mapping API fields to **kwargs.
AI agents deserve close review. A model may generate a branch, revision or Git-tool options after reading an untrusted issue. A typed tool schema is not enough when it permits an arbitrary argument dictionary. Prompt injection does not exploit these CVEs by itself, but can deliver a value to the vulnerable sink without deliberate human action.
CI runners often hold a repository token, registry credentials, artifact write rights and sometimes cloud credentials. Code execution while analysing a pull request can change build output or steal a secret. A persistent self-hosted runner increases the opportunity to retain access across jobs.
What to do now
- Locate GitPython in applications, images, notebooks and internal tools, proving the effective runtime version.
- Upgrade to 3.1.54 or later and rebuild images without a cached 3.1.53 wheel.
- Find calls to
clone_from, remote operations,iter_commits,blame,archiveanddiff, especially with external**kwargsor revisions. - Remove public submission of arbitrary options. Map to approved parameters and reject dash-prefixed values where a revision name is expected.
- Run Git in an ephemeral worker without secrets and with minimal write access; block hooks and unnecessary egress at system level.
- Review process logs, file modifications and token activity during the affected window where external data reached these methods.
- Add regression tests proving that the dangerous capability is blocked in a name, value and revision after argument transformation.
The dependency update must reach every environment. A Python lockfile may show a new release while an old wheel remains in an image layer or long-lived virtual environment. Evidence should be a runtime version and rebuilt image digest.
Detection and a safer design
Telemetry can identify child processes launched by git, unusual template, upload-pack and output options, hooks appearing in newly cloned repositories and writes outside the workspace. Avoid logging full URLs containing credentials. Record the method, approved host, redacted argv and job identifier.
A stronger boundary is a separate container with a read-only root, empty home directory and one work volume. Treat a repository as an untrusted artifact. If Git launches a hook or writes outside the workspace, the operating system should contain the effect even when a future validation defect appears.
Do not create another ever-growing denylist in the web controller. Define an allowlist of business features: a validated URL, approved revision, small depth range and server-created destination. Anything else should require a separate administrative path.
The three paths, scores and 3.1.54 fix are facts from GitPython advisories and the release changes. Those sources do not establish mass exploitation. CI risk, isolation and hunting are Breachroad recommendations. This is a strong case study for the data-to-argument boundary in our cybersecurity training for organisations. An independent cloud and DevSecOps assessment can review repository-processing pipelines and runner isolation.


