CVE-2026-110858
GitPython 3.1.30 before 3.2.0 Command Injection via Remote.pull() Refspec
GitPython from 3.1.30 before 3.2.0 contains a remote code execution vulnerability in Remote.pull() whose unsafe-option guard inspects only keyword arguments, not the positional refspec. Attackers controlling the refspec can supply --upload-pack=<command> to execute OS commands as the calling process over local-path or SSH transports.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
9.2
GitPython 3.1.30 before 3.2.0 Command Injection via Remote.pull() Refspec
GitPython from 3.1.30 before 3.2.0 contains a remote code execution vulnerability in Remote.pull() whose unsafe-option guard inspects only keyword arguments, not the positional refspec. Attackers controlling the refspec can supply --upload-pack=<command> to execute OS commands as the calling process over local-path or SSH transports.
- Record
CVE-2026-110858- CVSS 4.0
- 9.2 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-88
- Updated
- 2026-11-02
EUVDEUVD-2026-101741
9.2
GitPython from 3.1.30 before 3.2.0 contains a remote code execution vulnerability in Remote.pull() whose unsafe-option guard inspects only keyword arguments, not the positional refspec. Attackers controlling the refspec can supply --upload-pack=<command> to execute OS commands as the calling process over local-path or SSH transports.
- Record
EUVD-2026-101741- CVSS 4.0
- 9.2 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-f9j4-qggq-h239
8.1
GitPython Remote.pull() refspec bypasses the --upload-pack unsafe-option guard, enabling arbitrary command execution
Summary
Remote.pull() in GitPython forwards its positional refspec argument directly to the git pull child process while its unsafe-option guard inspects only keyword arguments. An application that passes attacker-influenced data as the refspec (for example a user-supplied branch or refspec parameter in a web or CI service) can supply an option-shaped value such as --upload-pack=<command>. The value bypasses the unsafe_git_pull_options check, is placed after the -- separator on the git pull command line, and is executed as the upload-pack program for local-path or SSH transports. This yields arbitrary command execution with the privileges of the calling process using the documented default arguments (allow_unsafe_options=False).
Root Cause
Remote.pull() is documented to reject dangerous options unless allow_unsafe_options=True, and --upload-pack is explicitly listed as such an option. The guard, however, only screens keyword arguments and never the positional refspec. The check builds its candidate list with Git._option_candidates([], kwargs), passing an empty list in place of the positionals, so the refspec value is never compared against unsafe_git_pull_options = ["--upload-pack"]. The normalized refspec is then forwarded verbatim to the git pull invocation. The leading -- separator that neutralizes an option-shaped refspec for git fetch and git push does not protect git pull, because git pull re-forwards its trailing positionals to an internal git fetch without re-inserting a -- separator, so the positional becomes an option to that internal fetch.
Affected function: git.remote.Remote.pull
Source: git/remote.py (guard at the check_unsafe_options call using _option_candidates([], kwargs); sink at the self.repo.git.pull("--", self, refspec, ...) invocation)
Impact
An attacker who controls the refspec value passed to Remote.pull() achieves arbitrary operating-system command execution as the process invoking GitPython, with no additional privileges and no user interaction, on the default code path. Exploitation requires that the pulled remote uses a transport that runs upload-pack on the local side, namely a local filesystem path or SSH; over HTTPS the --upload-pack value is inert because the server ignores a client-supplied upload-pack program. This transport requirement narrows the population of vulnerable deployments but does not add work for the attacker once a vulnerable target is reached. Working checkouts commonly use local-path or SSH origins, so the exposed population is substantial.
Proof of Concept
Environment: GitPython from the affected source tree; system git 2.43.0.
The pulled origin uses a local filesystem transport (protocol.file.allow=always for git >= 2.38).
Reproduction steps:
- Create an origin repository reachable over a local-path transport.
- In a consumer repository, register that origin and call
Remote.pull()with an attacker-controlled refspec. - Observe that the injected command executes.
import git
repo = git.Repo("consumer") # has an origin using a local-path or ssh transport
origin = repo.remote("origin")
# Attacker-controlled refspec value; default arguments (allow_unsafe_options=False):
origin.pull(refspec="--upload-pack=touch /tmp/pwned; git-upload-pack")
cmdline: git pull -v -- origin --upload-pack=touch /tmp/pwned; git-upload-pack
[attack] marker created (RCE) : True
[isolate] upload_pack passed as KWARG blocked : True (only the positional refspec escapes)
[sibling] same value via git fetch : safe (pull-specific behavior)
[control] benign refspec : safe
Attack Chain
- Exposure: An application calls
Remote.pull(refspec=<value>)on the default path, where<value>is derived from attacker-influenced input such as a branch or refspec request parameter. - Control: The attacker supplies the string…
- Record
GHSA-f9j4-qggq-h239- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-78, CWE-88
- Updated
- 2026-11-02
GitHub AdvisoriesGHSA-mcf4-6385-6rcq
9.2
GitPython from 3.1.30 before 3.2.0 contains a remote code execution vulnerability in Remote.pull(...
GitPython from 3.1.30 before 3.2.0 contains a remote code execution vulnerability in Remote.pull() whose unsafe-option guard inspects only keyword arguments, not the positional refspec. Attackers controlling the refspec can supply --upload-pack=<command> to execute OS commands as the calling process over local-path or SSH transports.
- Record
GHSA-mcf4-6385-6rcq- CVSS 4.0
- 9.2 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-88
- Updated
- 2026-11-02
NVD
9.2
GitPython from 3.1.30 before 3.2.0 contains a remote code execution vulnerability in Remote.pull() whose unsafe-option guard inspects only keyword arguments, not the positional refspec. Attackers controlling the refspec can supply --upload-pack=<command> to execute OS commands as the calling process over local-path or SSH transports.
- Record
CVE-2026-110858- CVSS 4.0
- 9.2 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-88
- Updated
- 2026-11-02
OSV
9.2
GitPython 3.1.30 before 3.2.0 Command Injection via Remote.pull() Refspec
GitPython from 3.1.30 before 3.2.0 contains a remote code execution vulnerability in Remote.pull() whose unsafe-option guard inspects only keyword arguments, not the positional refspec. Attackers controlling the refspec can supply --upload-pack=<command> to execute OS commands as the calling process over local-path or SSH transports.
- Record
CVE-2026-110858- CVSS 4.0
- 9.2 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-88
- Updated
- 2026-11-03
Show 7 moreShow less
OSVDEBIAN-CVE-2026-110858
9.2
GitPython from 3.1.30 before 3.2.0 contains a remote code execution vulnerability in Remote.pull() whose unsafe-option guard inspects only keyword arguments, not the positional refspec. Attackers controlling the refspec can supply --upload-pack=<command> to execute OS commands as the calling process over local-path or SSH transports.
- Record
DEBIAN-CVE-2026-110858- CVSS 4.0
- 9.2 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Updated
- 2026-11-02
OSVGHSA-f9j4-qggq-h239
8.1
GitPython Remote.pull() refspec bypasses the --upload-pack unsafe-option guard, enabling arbitrary command execution
Summary
Remote.pull() in GitPython forwards its positional refspec argument directly to the git pull child process while its unsafe-option guard inspects only keyword arguments. An application that passes attacker-influenced data as the refspec (for example a user-supplied branch or refspec parameter in a web or CI service) can supply an option-shaped value such as --upload-pack=<command>. The value bypasses the unsafe_git_pull_options check, is placed after the -- separator on the git pull command line, and is executed as the upload-pack program for local-path or SSH transports. This yields arbitrary command execution with the privileges of the calling process using the documented default arguments (allow_unsafe_options=False).
Root Cause
Remote.pull() is documented to reject dangerous options unless allow_unsafe_options=True, and --upload-pack is explicitly listed as such an option. The guard, however, only screens keyword arguments and never the positional refspec. The check builds its candidate list with Git._option_candidates([], kwargs), passing an empty list in place of the positionals, so the refspec value is never compared against unsafe_git_pull_options = ["--upload-pack"]. The normalized refspec is then forwarded verbatim to the git pull invocation. The leading -- separator that neutralizes an option-shaped refspec for git fetch and git push does not protect git pull, because git pull re-forwards its trailing positionals to an internal git fetch without re-inserting a -- separator, so the positional becomes an option to that internal fetch.
Affected function: git.remote.Remote.pull
Source: git/remote.py (guard at the check_unsafe_options call using _option_candidates([], kwargs); sink at the self.repo.git.pull("--", self, refspec, ...) invocation)
Impact
An attacker who controls the refspec value passed to Remote.pull() achieves arbitrary operating-system command execution as the process invoking GitPython, with no additional privileges and no user interaction, on the default code path. Exploitation requires that the pulled remote uses a transport that runs upload-pack on the local side, namely a local filesystem path or SSH; over HTTPS the --upload-pack value is inert because the server ignores a client-supplied upload-pack program. This transport requirement narrows the population of vulnerable deployments but does not add work for the attacker once a vulnerable target is reached. Working checkouts commonly use local-path or SSH origins, so the exposed population is substantial.
Proof of Concept
Environment: GitPython from the affected source tree; system git 2.43.0.
The pulled origin uses a local filesystem transport (protocol.file.allow=always for git >= 2.38).
Reproduction steps:
- Create an origin repository reachable over a local-path transport.
- In a consumer repository, register that origin and call
Remote.pull()with an attacker-controlled refspec. - Observe that the injected command executes.
import git
repo = git.Repo("consumer") # has an origin using a local-path or ssh transport
origin = repo.remote("origin")
# Attacker-controlled refspec value; default arguments (allow_unsafe_options=False):
origin.pull(refspec="--upload-pack=touch /tmp/pwned; git-upload-pack")
cmdline: git pull -v -- origin --upload-pack=touch /tmp/pwned; git-upload-pack
[attack] marker created (RCE) : True
[isolate] upload_pack passed as KWARG blocked : True (only the positional refspec escapes)
[sibling] same value via git fetch : safe (pull-specific behavior)
[control] benign refspec : safe
Attack Chain
- Exposure: An application calls
Remote.pull(refspec=<value>)on the default path, where<value>is derived from attacker-influenced input such as a branch or refspec request parameter. - Control: The attacker supplies the string…
- Record
GHSA-f9j4-qggq-h239- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-78, CWE-88
- Updated
- 2026-11-02
OSVUBUNTU-CVE-2026-110858
9.2
GitPython from 3.1.30 before 3.2.0 contains a remote code execution vulnerability in Remote.pull() whose unsafe-option guard inspects only keyword arguments, not the positional refspec. Attackers controlling the refspec can supply --upload-pack=<command> to execute OS commands as the calling process over local-path or SSH transports.
- Record
UBUNTU-CVE-2026-110858- CVSS 4.0
- 9.2 Critical
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H - Updated
- 2026-11-02
OSVCLSA-2026-1792479054 No score
TuxCare security update for gitpython (7 CVEs)
TuxCare rebuilt gitpython to address 7 CVEs. Fixed in 3.1.31.post15+tuxcare.
- Record
CLSA-2026-1792479054- Updated
- 2026-11-02
OSVCLSA-2026-1793612016 No score
TuxCare security update for gitpython (1 CVE)
TuxCare rebuilt gitpython to address 1 CVE. Fixed in 3.1.31.post18+tuxcare.
- Record
CLSA-2026-1793612016- Updated
- 2026-11-02
OSVMGASA-2026-0580 No score
Updated python-gitpython package fixes security vulnerabilities
Please see the links for additional information.
- Record
MGASA-2026-0580- Updated
- 2026-11-07
OSVopenSUSE-SU-2026:12391-1 No score
python313-GitPython-3.2.1-1.1 on GA media
These are all security issues fixed in the python313-GitPython-3.2.1-1.1 package on the GA media of openSUSE Tumbleweed.
- Record
openSUSE-SU-2026:12391-1- Updated
- 2026-11-03
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
gitpythonPyPI |
3.1.30 up to 3.2.0 | 3.2.0 |
gitpythonTuxCare:PyPI From an advisory covering 4 CVEs |
3.1.31 up to 3.1.31.post15+tuxcare, plus listed versions 3.1.31.post1+tuxcare3.1.31.post10+tuxcare3.1.31.post11+tuxcare3.1.31.post12+tuxcare3.1.31.post13+tuxcare Show 9 moreShow less3.1.31.post14+tuxcare3.1.31.post2+tuxcare3.1.31.post3+tuxcare3.1.31.post4+tuxcare3.1.31.post5+tuxcare3.1.31.post6+tuxcare3.1.31.post7+tuxcare3.1.31.post8+tuxcare3.1.31.post9+tuxcare |
3.1.31.post15+tuxcare |
gitpythonTuxCare:PyPI |
3.1.31 up to 3.1.31.post18+tuxcare, plus listed versions 3.1.31.post1+tuxcare3.1.31.post10+tuxcare3.1.31.post11+tuxcare3.1.31.post12+tuxcare3.1.31.post13+tuxcare Show 12 moreShow less3.1.31.post14+tuxcare3.1.31.post15+tuxcare3.1.31.post16+tuxcare3.1.31.post17+tuxcare3.1.31.post2+tuxcare3.1.31.post3+tuxcare3.1.31.post4+tuxcare3.1.31.post5+tuxcare3.1.31.post6+tuxcare3.1.31.post7+tuxcare3.1.31.post8+tuxcare3.1.31.post9+tuxcare |
3.1.31.post18+tuxcare |
python-gitDebian:12 |
before 3.1.30-1+deb12u3, plus listed versions 3.1.30-13.1.30-1+deb12u2 |
3.1.30-1+deb12u3 |
python-gitDebian:13 |
before 3.1.44-1+deb13u1, plus listed versions 3.1.44-1 |
3.1.44-1+deb13u1 |
python-gitDebian:14 |
before 3.2.1-1, plus listed versions 3.1.44-13.1.45-13.1.46-13.1.50-13.1.61-13.1.62-13.1.62-23.1.62-3 |
3.2.1-1 |
gitpythonPyPI |
3.1.30 up to 3.2.0, plus listed versions 3.1.313.1.323.1.333.1.343.1.35 Show 26 moreShow less3.1.363.1.373.1.383.1.403.1.413.1.423.1.433.1.443.1.453.1.463.1.473.1.483.1.493.1.503.1.513.1.523.1.533.1.543.1.553.1.563.1.573.1.583.1.593.1.603.1.613.1.62 |
3.2.0 |
python-gitpythonMageia:10 From an advisory covering 6 CVEs |
before 3.2.1-1.mga10 | 3.2.1-1.mga10 |
python-gitUbuntu:Pro:14.04:LTS |
All versions, plus listed versions 0.3.2~RC1-20.3.2~RC1-30.3.2~RC1-3ubuntu0.1~esm10.3.2~RC1-3ubuntu0.1~esm20.3.2~RC1-3ubuntu0.1~esm3 |
None known |
python-gitUbuntu:Pro:16.04:LTS |
All versions, plus listed versions 1.0.1+git137-gc8b8379-11.0.1+git137-gc8b8379-21.0.1+git137-gc8b8379-2.11.0.1+git137-gc8b8379-2.1ubuntu0.1~esm11.0.1+git137-gc8b8379-2.1ubuntu0.1~esm21.0.1+git137-gc8b8379-2.1ubuntu0.1~esm4 |
None known |
Show 7 moreShow less
| Package | Affected | Fixed |
|---|---|---|
python-gitUbuntu:Pro:18.04:LTS |
All versions, plus listed versions 2.1.5-12.1.6-12.1.7-12.1.8-12.1.8-1ubuntu0.1~esm12.1.8-1ubuntu0.1~esm22.1.8-1ubuntu0.1~esm4 |
None known |
python-gitUbuntu:Pro:20.04:LTS |
All versions, plus listed versions 2.1.11-13.0.4-13.0.5-13.0.7-13.0.7-1ubuntu0.1~esm13.0.7-1ubuntu0.1~esm23.0.7-1ubuntu0.1~esm4 |
None known |
python-gitUbuntu:Pro:22.04:LTS |
All versions, plus listed versions 3.1.14-13.1.23-13.1.24-13.1.24-1ubuntu0.1~esm13.1.24-1ubuntu0.1~esm23.1.24-1ubuntu0.1~esm3 |
None known |
python-gitUbuntu:Pro:24.04:LTS |
All versions, plus listed versions 3.1.30-13.1.37-13.1.37-33.1.37-3ubuntu0.1~esm2 |
None known |
python-gitUbuntu:26.10 |
All versions, plus listed versions 3.1.46-13.1.50-13.1.61-1 |
None known |
python-gitUbuntu:Pro:26.04:LTS |
All versions, plus listed versions 3.1.44-13.1.45-13.1.46-13.1.46-1ubuntu0.1~esm1 |
None known |
python-GitPythonopenSUSE:Tumbleweed From an advisory covering 6 CVEs |
before 3.2.1-1.1 | 3.2.1-1.1 |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected, aliases, references | OSV | |
| affected | ||
| affected, aliases, facts, references | OSV | |
| affected, aliases, references | ||
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-110858 is a critical vulnerability (CVSS 9.2) in Gitpython-developers Gitpython, published October 14, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.46%, the 40th percentile. Fixed in gitpython 3.2.0.
References
github.com/gitpython-developers/GitPython/security/advisories/GHSA-f9j4-qggq-h239
vulncheck.com/advisories/gitpython-3.1.30-before-3.2.0-command-injection-via-remote-pull-refspec
github.com/gitpython-developers/GitPython/pull/2247
github.com/gitpython-developers/GitPython/commit/790bb3164948625ffb043d2a162425d55923fe9a
github.com/gitpython-developers/GitPython/releases/tag/3.2.0
github.com/advisories/GHSA-f9j4-qggq-h239
Show 17 moreShow less
nvd.nist.gov/vuln/detail/CVE-2026-110858
github.com/advisories/GHSA-mcf4-6385-6rcq
github.com/CVEProject/cvelistV5/tree/main/cves/2026/110xxx/CVE-2026-110858.json
security-tracker.debian.org/tracker/CVE-2026-110858
github.com/gitpython-developers/GitPython
advisories.mageia.org/MGASA-2026-0580.html
bugs.mageia.org/show_bug.cgi?id=36507
github.com/gitpython-developers/GitPython/releases
lists.fedoraproject.org/archives/list/[email protected]/message/OOS5EDMLYZWKECAUWB5INCTGXLGARLNL
ubuntu.com/security/CVE-2026-110858
cve.org/CVERecord?id=CVE-2026-110858
suse.com/security/cve/CVE-2026-110855
suse.com/security/cve/CVE-2026-110856
suse.com/security/cve/CVE-2026-110857
suse.com/security/cve/CVE-2026-110858
suse.com/security/cve/CVE-2026-110859
suse.com/security/cve/CVE-2026-114145
Left out here: the rest of 2 source descriptions. The JSON record has them.