CVE-2026-110857
GitPython before 3.2.0 Command Execution via ls_remote ext:: URLs
GitPython before 3.2.0 contains a remote code execution vulnerability that allows attackers to run commands because Git.ls_remote forwards URLs without check_unsafe_protocols validation. Attackers can supply ext:: remote-helper URLs to execute commands when git permits the ext transport, while merge_base and IndexFile.move also accept unguarded option injection.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- High
- Privileges needed
- None
- User interaction
- Passive
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
7.7
GitPython before 3.2.0 Command Execution via ls_remote ext:: URLs
GitPython before 3.2.0 contains a remote code execution vulnerability that allows attackers to run commands because Git.ls_remote forwards URLs without check_unsafe_protocols validation. Attackers can supply ext:: remote-helper URLs to execute commands when git permits the ext transport, while merge_base and IndexFile.move also accept unguarded option injection.
- Record
CVE-2026-110857- CVSS 4.0
- 7.7 High
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-1287
- Updated
- 2026-11-02
EUVDEUVD-2026-101740
7.7
GitPython before 3.2.0 contains a remote code execution vulnerability that allows attackers to run commands because Git.ls_remote forwards URLs without check_unsafe_protocols validation. Attackers can supply ext:: remote-helper URLs to execute commands when git permits the ext transport, while merge_base and IndexFile.move also accept unguarded option injection.
- Record
EUVD-2026-101740- CVSS 4.0
- 7.7 High
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-jj45-mj3g-556c
7.7
GitPython before 3.2.0 contains a remote code execution vulnerability that allows attackers to...
GitPython before 3.2.0 contains a remote code execution vulnerability that allows attackers to run commands because Git.ls_remote forwards URLs without check_unsafe_protocols validation. Attackers can supply ext:: remote-helper URLs to execute commands when git permits the ext transport, while merge_base and IndexFile.move also accept unguarded option injection.
- Record
GHSA-jj45-mj3g-556c- CVSS 4.0
- 7.7 High
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/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
- 7.5 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-1287
- Updated
- 2026-11-02
GitHub AdvisoriesGHSA-w8jc-g24h-crhw
7.5
GitPython command wrappers omit unsafe protocol and option checks
Summary
GitPython has spent 2022-2026 rolling out two reusable guards method-by-method: Git.check_unsafe_protocols(url) (raises UnsafeProtocolError for <transport>:: remote-helper URLs - CVE-2022-24439) and Git.check_unsafe_options(...) (raises UnsafeOptionError for denylisted option spellings - CVE-2023-40267, CVE-2026-42215, CVE-2026-67323). Three wrapper methods that build a git argv from caller-controlled values still have neither:
Git.ls_remote(git/cmd.py:1128-1143) - checks options (:1139-1141) but forwards the URL positional unchecked; noallow_unsafe_protocolsparameter exists. The same URL throughclone_fromraisesUnsafeProtocolError.Repo.merge_base(git/repo/base.py:895-936) - forwards**kwargs/*revtoself.git.merge_basewith no guard; guarded siblingiter_commitssits 12 lines up. Its exception handler additionally swallows every non-128GitCommandErrorinto[], masking the injection.IndexFile.move(git/index/base.py:1092-1168) - forwards**kwargstogit mvtwice (:1147, :1167); guarded siblingremove()is 23 lines above.
Verified unfixed on main @ a54d159 (2026-09-21), post-dating latest release 3.1.62 (2026-09-07) - all three sites re-verified today.
Impact
Site 1 (ls_remote) - RCE conditional on the victim git transport policy. The common 'probe first, then clone' pattern (Git(...).ls_remote(attacker_url)) with an ext::sh -c ... URL executes arbitrary commands when the victim git permits the ext transport: dynamically verified with protocol.ext.allow=always (marker executed). git >= 2.38.1 stock config refuses the transport (fatal: transport 'ext' not allowed, rc 128) - GitPython adds no defense-in-depth and surfaces a bare GitCommandError. Environments on git < 2.38.1 are exposed with stock config - the exact population CVE-2022-24439 was scored against.
Sites 2/3 - latent argument-injection surface: caller kwargs flow 1:1 into the git argv before operands and -- (cmd.py:1850 opt_args + ext_args), and execute_kwargs (incl. shell=True/env - the CVE-2023-40267 Windows mechanism) passes through unguarded. Today git merge-base/git mv expose no exec option, so we claim the missing-guard class (vendor-settled by CVE-2026-67323, which bundled archive/ls_remote/iter_commits/blame in one advisory), not direct RCE.
Dynamic verification (today; GitPython main @ a54d159, git 2.55.0, Linux)
| # | Call | Result |
|---|---|---|
| T1 | repo.git.ls_remote('ext::/tmp/gp_touch.sh'), stock config | git refuses (rc 128); no UnsafeProtocolError from GitPython |
| T1b | same + victim config protocol.ext.allow=always | marker created - arbitrary command executed |
| T2 | repo.git.ls_remote('.', upload_pack=...) | blocked by cmd.py:1141 (options-side fixed - protocol-side is the residual gap) |
| T3 | repo.merge_base('main','side', upload_pack=...) | not blocked; argv git merge-base --upload-pack=... main side; rc 129 silently converted to [] |
| T4 | repo.index.move(['f1','f2'], output=...) | not blocked; option reaches git mv (rc 129) |
Coverage matrix (main @ a54d159)
check_unsafe_protocols: 7 call sites (_clone, archive, set_url, create, fetch, pull, push) - none on ls_remote.
check_unsafe_options: 24 call sites incl. ls_remote, iter_commits, IndexFile.remove - absent on merge_base and move.
Precedents (same repo, same guard family)
- CVE-2022-24439 / GHSA-hcpj-qp55-gfph (critical):
check_unsafe_protocolson the clone path - Site 1 is the sameext::primitive on a sibling API. - CVE-2023-40267 / GHSA-pr76-5cm5-w9cj (critical, 'incomplete fix for CVE-2022-24439'):
check_unsafe_options- unguarded kwargs to argv treated as RCE (shell=Trueon Windows). - CVE-2026-42215 / GHSA-rpm5-65cw-6hj4 (high, fixed 3.1.47): underscored-spelling bypass - rollout still active in 2026.
- CVE-2026-67323 / GHSA-956x-8gvw-wg5v…
- Record
GHSA-w8jc-g24h-crhw- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-1287
- Updated
- 2026-11-02
NVD
7.7
GitPython before 3.2.0 contains a remote code execution vulnerability that allows attackers to run commands because Git.ls_remote forwards URLs without check_unsafe_protocols validation. Attackers can supply ext:: remote-helper URLs to execute commands when git permits the ext transport, while merge_base and IndexFile.move also accept unguarded option injection.
- Record
CVE-2026-110857- CVSS 4.0
- 7.7 High
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/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
- 7.5 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-1287
- Updated
- 2026-11-02
OSV
7.7
GitPython before 3.2.0 Command Execution via ls_remote ext:: URLs
GitPython before 3.2.0 contains a remote code execution vulnerability that allows attackers to run commands because Git.ls_remote forwards URLs without check_unsafe_protocols validation. Attackers can supply ext:: remote-helper URLs to execute commands when git permits the ext transport, while merge_base and IndexFile.move also accept unguarded option injection.
- Record
CVE-2026-110857- CVSS 4.0
- 7.7 High
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-1287
- Updated
- 2026-11-03
Show 6 moreShow less
OSVDEBIAN-CVE-2026-110857
7.7
GitPython before 3.2.0 contains a remote code execution vulnerability that allows attackers to run commands because Git.ls_remote forwards URLs without check_unsafe_protocols validation. Attackers can supply ext:: remote-helper URLs to execute commands when git permits the ext transport, while merge_base and IndexFile.move also accept unguarded option injection.
- Record
DEBIAN-CVE-2026-110857- CVSS 4.0
- 7.7 High
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/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-w8jc-g24h-crhw
7.5
GitPython command wrappers omit unsafe protocol and option checks
Summary
GitPython has spent 2022-2026 rolling out two reusable guards method-by-method: Git.check_unsafe_protocols(url) (raises UnsafeProtocolError for <transport>:: remote-helper URLs - CVE-2022-24439) and Git.check_unsafe_options(...) (raises UnsafeOptionError for denylisted option spellings - CVE-2023-40267, CVE-2026-42215, CVE-2026-67323). Three wrapper methods that build a git argv from caller-controlled values still have neither:
Git.ls_remote(git/cmd.py:1128-1143) - checks options (:1139-1141) but forwards the URL positional unchecked; noallow_unsafe_protocolsparameter exists. The same URL throughclone_fromraisesUnsafeProtocolError.Repo.merge_base(git/repo/base.py:895-936) - forwards**kwargs/*revtoself.git.merge_basewith no guard; guarded siblingiter_commitssits 12 lines up. Its exception handler additionally swallows every non-128GitCommandErrorinto[], masking the injection.IndexFile.move(git/index/base.py:1092-1168) - forwards**kwargstogit mvtwice (:1147, :1167); guarded siblingremove()is 23 lines above.
Verified unfixed on main @ a54d159 (2026-09-21), post-dating latest release 3.1.62 (2026-09-07) - all three sites re-verified today.
Impact
Site 1 (ls_remote) - RCE conditional on the victim git transport policy. The common 'probe first, then clone' pattern (Git(...).ls_remote(attacker_url)) with an ext::sh -c ... URL executes arbitrary commands when the victim git permits the ext transport: dynamically verified with protocol.ext.allow=always (marker executed). git >= 2.38.1 stock config refuses the transport (fatal: transport 'ext' not allowed, rc 128) - GitPython adds no defense-in-depth and surfaces a bare GitCommandError. Environments on git < 2.38.1 are exposed with stock config - the exact population CVE-2022-24439 was scored against.
Sites 2/3 - latent argument-injection surface: caller kwargs flow 1:1 into the git argv before operands and -- (cmd.py:1850 opt_args + ext_args), and execute_kwargs (incl. shell=True/env - the CVE-2023-40267 Windows mechanism) passes through unguarded. Today git merge-base/git mv expose no exec option, so we claim the missing-guard class (vendor-settled by CVE-2026-67323, which bundled archive/ls_remote/iter_commits/blame in one advisory), not direct RCE.
Dynamic verification (today; GitPython main @ a54d159, git 2.55.0, Linux)
| # | Call | Result |
|---|---|---|
| T1 | repo.git.ls_remote('ext::/tmp/gp_touch.sh'), stock config | git refuses (rc 128); no UnsafeProtocolError from GitPython |
| T1b | same + victim config protocol.ext.allow=always | marker created - arbitrary command executed |
| T2 | repo.git.ls_remote('.', upload_pack=...) | blocked by cmd.py:1141 (options-side fixed - protocol-side is the residual gap) |
| T3 | repo.merge_base('main','side', upload_pack=...) | not blocked; argv git merge-base --upload-pack=... main side; rc 129 silently converted to [] |
| T4 | repo.index.move(['f1','f2'], output=...) | not blocked; option reaches git mv (rc 129) |
Coverage matrix (main @ a54d159)
check_unsafe_protocols: 7 call sites (_clone, archive, set_url, create, fetch, pull, push) - none on ls_remote.
check_unsafe_options: 24 call sites incl. ls_remote, iter_commits, IndexFile.remove - absent on merge_base and move.
Precedents (same repo, same guard family)
- CVE-2022-24439 / GHSA-hcpj-qp55-gfph (critical):
check_unsafe_protocolson the clone path - Site 1 is the sameext::primitive on a sibling API. - CVE-2023-40267 / GHSA-pr76-5cm5-w9cj (critical, 'incomplete fix for CVE-2022-24439'):
check_unsafe_options- unguarded kwargs to argv treated as RCE (shell=Trueon Windows). - CVE-2026-42215 / GHSA-rpm5-65cw-6hj4 (high, fixed 3.1.47): underscored-spelling bypass - rollout still active in 2026.
- CVE-2026-67323 / GHSA-956x-8gvw-wg5v…
- Record
GHSA-w8jc-g24h-crhw- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H - Weakness
- CWE-1287
- Updated
- 2026-11-02
OSVUBUNTU-CVE-2026-110857
7.7
GitPython before 3.2.0 contains a remote code execution vulnerability that allows attackers to run commands because Git.ls_remote forwards URLs without check_unsafe_protocols validation. Attackers can supply ext:: remote-helper URLs to execute commands when git permits the ext transport, while merge_base and IndexFile.move also accept unguarded option injection.
- Record
UBUNTU-CVE-2026-110857- CVSS 4.0
- 7.7 High
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N - CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H - Updated
- 2026-11-02
OSVCLSA-2026-1792480708 No score
TuxCare security update for gitpython (2 CVEs)
TuxCare rebuilt gitpython to address 2 CVEs. Fixed in 3.1.31.post16+tuxcare.
- Record
CLSA-2026-1792480708- 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 |
through 3.1.62 | 3.2.0 |
gitpythonTuxCare:PyPI |
3.1.31 up to 3.1.31.post16+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 10 moreShow less3.1.31.post14+tuxcare3.1.31.post15+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.post16+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 |
before 3.2.0, plus listed versions 0.1.70.2.0-beta10.3.0-beta10.3.0-beta20.3.1-beta2 Show 45 moreShow less0.3.20.3.2.10.3.2.RC10.3.30.3.40.3.50.3.60.3.71.0.01.0.11.0.22.0.02.0.12.0.22.0.32.0.42.0.52.0.62.0.72.0.82.0.92.0.9.dev02.0.9.dev12.1.02.1.12.1.102.1.112.1.122.1.132.1.142.1.152.1.22.1.32.1.42.1.52.1.62.1.72.1.82.1.93.0.03.0.13.0.23.0.33.0.43.0.5 |
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 |
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 |
Show 6 moreShow less
| Package | Affected | Fixed |
|---|---|---|
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-110857 is a high vulnerability (CVSS 7.7) 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.42%, the 36th percentile. Fixed in gitpython 3.2.0.
References
github.com/gitpython-developers/GitPython/security/advisories/GHSA-w8jc-g24h-crhw
vulncheck.com/advisories/gitpython-before-3.2.0-command-execution-via-ls-remote-ext-urls
nvd.nist.gov/vuln/detail/CVE-2026-110857
github.com/advisories/GHSA-jj45-mj3g-556c
github.com/gitpython-developers/GitPython/pull/2251
github.com/gitpython-developers/GitPython/commit/9ad28cc4c7176d22cd6181d69805058a719dd03b
Show 17 moreShow less
github.com/gitpython-developers/GitPython/releases/tag/3.2.0
github.com/advisories/GHSA-w8jc-g24h-crhw
github.com/CVEProject/cvelistV5/tree/main/cves/2026/110xxx/CVE-2026-110857.json
security-tracker.debian.org/tracker/CVE-2026-110857
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-110857
cve.org/CVERecord?id=CVE-2026-110857
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: 65 versions and the rest of 2 source descriptions. The JSON record has them.