Summary
GitPython: Unsafe git option guard bypass via single-character kwarg value token smuggling enables arbitrary command execution
GitPython's check_unsafe_options guard (the control introduced by CVE-2026-42215 / GHSA-2f96 and hardened since) can be bypassed for every guarded method (clone/clone_from, fetch/pull/push, ls_remote, iter_commits, blame, archive) by smuggling an option token inside the VALUE of a single-character kwarg. In the default allow_unsafe_options=False configuration this yields arbitrary command execution via --upload-pack.
Root Cause
The guard builds its candidate option list from kwarg KEYS only: _option_candidates([], {"n":"--upload-pack=<cmd>"}) returns ['-n'] (cmd.py:1042-1046 derives the candidate from the key, never the value). -n is not on the denylist, so check_unsafe_options passes. But transform_kwarg('n', value, split_single_char_options=True) (cmd.py:1600-1606) emits two argv tokens ['-n', '--upload-pack=<cmd>']. git then parses the second token as --upload-pack and executes the attacker-supplied command. The guard never inspects the value that becomes a separate argv token.
Proof of Concept
from git import Repo
Repo.clone_from(bare_repo, out_dir, n="--upload-pack=touch /tmp/ACE;git-upload-pack")
# /tmp/ACE created -> ACE. Direct-name form upload_pack="..." is correctly BLOCKED.
File-write variant on a guarded revision command: iter_commits('HEAD', g='--output=/path') -> candidate ['-g'] passes, argv ['-g','--output=/path'], victim file truncated.
Attack Chain
- Entry: app forwards a user-supplied options dict ->
Repo.clone_from(url, path, n="--upload-pack=touch /tmp/ACE;git-upload-pack"). Guard:check_unsafe_options(options=_option_candidates([], kwargs), unsafe=unsafe_git_clone_options)at base.py. Bypass proof:_option_candidates([], {"n":"--upload-pack=..."})->['-n'](key-only), not on denylist -> no UnsafeOptionError (verified live). - Transform:
transform_kwarg('n', value, split_single_char_options=True)->['-n', '--upload-pack=touch /tmp/ACE;git-upload-pack']. Guard: none (guard already passed on name-only candidate). Bypass proof: verified transform emits two tokens. - Sink:
git clone -n --upload-pack='touch ...;git-upload-pack' -- <src> <dst>; git parses and runs the second token. Impact: ACE (marker created, verified end-to-end).
Bypass Evidence
Live-verified on HEAD (tag 3.1.53): _option_candidates returns key-only candidate ['-n']; transform_kwargs emits the smuggled --upload-pack= token; clone_from with the payload created the marker file; the direct-name upload_pack= form raised UnsafeOptionError. All prior bypasses (GHSA-rpm5 underscore key, GHSA-2f96 long-option abbreviation, GHSA-v396 joined short option, GHSA-x2qx multi-before-split) are BLOCKED on HEAD, this is a distinct kwarg-value->separate-token vector.
Affected Versions
<= 3.1.53
Impact
Arbitrary OS command execution as the host process (via --upload-pack) in the default configuration, affecting all guarded methods since they all build candidates through the name-only _option_candidates.
Untrusted input reaches a shell command, allowing arbitrary commands to run on the host. Typical impact: code execution in the application's environment.
GHSA-R9MR-M37C-5FR3 has a CVSS score of 8.8 (High). The vector is network-reachable, low privileges required, and no user interaction. A CVSS score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether this affects your application depends on whether the vulnerable code is present and reachable in your environment. A fixed version is available (3.1.54); upgrading removes the vulnerable code path.
Affected versions
Security releases
Kodem intelligence
Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.
Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.
Already deployed Kodem?
See it in your environmentNew to Kodem? Get a demo →Remediation advice
Make _option_candidates also emit candidates derived from single-character kwarg VALUES when split_single_char_options is in effect, OR run check_unsafe_options over the fully-transformed argv rather than the reconstructed name-only candidate list.
Reported by zx (Jace), GitHub: @manus-use
Frequently Asked Questions
- What is GHSA-R9MR-M37C-5FR3? GHSA-R9MR-M37C-5FR3 is a high-severity OS command injection vulnerability in GitPython (pip), affecting versions <= 3.1.53. It is fixed in 3.1.54. Untrusted input reaches a shell command, allowing arbitrary commands to run on the host.
- How severe is GHSA-R9MR-M37C-5FR3? GHSA-R9MR-M37C-5FR3 has a CVSS score of 8.8 (High). This score reflects the worst-case severity of the vulnerability, not your specific exposure. Whether it represents real risk in your environment depends on whether the vulnerable code is present and reachable.
- Which versions of GitPython are affected by GHSA-R9MR-M37C-5FR3? GitPython (pip) versions <= 3.1.53 is affected.
- Is there a fix for GHSA-R9MR-M37C-5FR3? Yes. GHSA-R9MR-M37C-5FR3 is fixed in 3.1.54. Upgrade to this version or later.
- Is GHSA-R9MR-M37C-5FR3 exploitable, and should I be worried? Whether GHSA-R9MR-M37C-5FR3 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
- What actually determines whether GHSA-R9MR-M37C-5FR3 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
- How do I fix GHSA-R9MR-M37C-5FR3? Upgrade
GitPythonto 3.1.54 or later.