{"id":"CVE-2026-87818","aliases":["DEBIAN-CVE-2026-87818","EUVD-2026-74844","GHSA-rw58-wc66-99g4","GHSA-whh4-5q6c-9v3x","OESA-2026-4025","OESA-2026-4026","OESA-2026-4027","PYSEC-2026-3983","SUSE-SU-2026:4191-1","UBUNTU-CVE-2026-87818","openSUSE-SU-2026:21874-1"],"status":"published","title":"GitPython 3.1.59 Local File Content Oracle via --no-index","description":"GitPython 3.1.59 fails to restrict the --no-index option in the high-level diff API, allowing attackers to read arbitrary filesystem paths as repository operands. Attackers can combine --no-index with -I/--ignore-matching-lines to create a content-dependent Boolean oracle, repeatedly querying local files to recover single-line secrets through distinguishable success or error responses.","severity":{"version":"4.0","score":7.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-12","score":0.00412,"percentile":0.35948,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-200","CWE-88"],"published":"2026-09-09T11:21:04Z","modified":"2026-10-31T14:00:10Z","fixes":[{"ecosystem":"PyPI","package":"gitpython","fixed_in":["3.1.60"],"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"]}],"affected":[{"source":"ghsa","ecosystem":"PyPI","package":"gitpython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.1.59"},{"fixed":"3.1.60"}]}]},{"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":"3.1.59"},{"fixed":"3.1.60"}]}],"versions":["3.1.59"]},{"source":"osv","ecosystem":"openEuler:24.03-LTS-SP1","package":"python-GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.59-2.oe2403sp1"}]}],"bundled":3},{"source":"osv","ecosystem":"openEuler:24.03-LTS-SP3","package":"python-GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.59-2.oe2403sp3"}]}],"bundled":3},{"source":"osv","ecosystem":"openEuler:24.03-LTS-SP4","package":"python-GitPython","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3.1.59-2.oe2403sp4"}]}],"bundled":3},{"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.11.1"}]}],"bundled":3},{"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.11.1"}]}],"bundled":3},{"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.11.1"}]}],"bundled":3},{"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.11.1"}]}],"bundled":3},{"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.11.1"}]}],"bundled":3},{"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.11.1"}]}],"bundled":3},{"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.11.1"}]}],"bundled":3},{"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.11.1"}]}],"bundled":3},{"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.11.1"}]}],"bundled":3},{"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.11.1"}]}],"bundled":3},{"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.11.1"}]}],"bundled":3},{"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: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: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-whh4-5q6c-9v3x","tags":["vendor-advisory","Exploit","Vendor Advisory","advisory","web","evidence","report"]},{"url":"https://www.vulncheck.com/advisories/gitpython-3.1.59-local-file-content-oracle-via-no-index","tags":["third-party-advisory","Third Party Advisory","advisory","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-87818","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-rw58-wc66-99g4","tags":["advisory"]},{"url":"https://github.com/gitpython-developers/GitPython/pull/2217","tags":["web"]},{"url":"https://github.com/gitpython-developers/GitPython/commit/09f2cf383a992d1af697364569e9f384748c1bd8","tags":["web"]},{"url":"https://github.com/gitpython-developers/GitPython/releases/tag/3.1.60","tags":["web"]},{"url":"https://github.com/pypa/advisory-database/tree/main/vulns/gitpython/PYSEC-2026-3983.yaml","tags":["web"]},{"url":"https://github.com/advisories/GHSA-whh4-5q6c-9v3x"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/87xxx/CVE-2026-87818.json","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-87818","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-4025","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-87817","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-87819","tags":["advisory"]},{"url":"https://www.openeuler.org/zh/security/security-bulletins/detail/?id=openEuler-SA-2026-4026","tags":["advisory"]},{"url":"https://www.openeuler.org/zh/security/security-bulletins/detail/?id=openEuler-SA-2026-4027","tags":["advisory"]},{"url":"https://www.suse.com/support/update/announcement/2026/suse-su-20264191-1/","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"]},{"url":"https://ubuntu.com/security/CVE-2026-87818","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-87818","tags":["report"]},{"url":"","tags":["advisory"]},{"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-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"]}],"sources":{"cve":[{"id":"CVE-2026-87818","title":"GitPython 3.1.59 Local File Content Oracle via --no-index","description":"GitPython 3.1.59 fails to restrict the --no-index option in the high-level diff API, allowing attackers to read arbitrary filesystem paths as repository operands. Attackers can combine --no-index with -I/--ignore-matching-lines to create a content-dependent Boolean oracle, repeatedly querying local files to recover single-line secrets through distinguishable success or error responses.","status":"published","published":"2026-09-09T11:21:04.681Z","modified":"2026-10-08T15:25:57.055Z","cvss":[{"version":"4.0","score":7.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N","level":"high","assessor":"cna"},{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N","level":"medium","assessor":"cna"}],"cwes":["CWE-88"],"updated_at":"2026-11-02T13:37:58.613221Z"}],"euvd":[{"id":"EUVD-2026-74844","description":"GitPython 3.1.59 fails to restrict the --no-index option in the high-level diff API, allowing attackers to read arbitrary filesystem paths as repository operands. Attackers can combine --no-index with -I/--ignore-matching-lines to create a content-dependent Boolean oracle, repeatedly querying local files to recover single-line secrets through distinguishable success or error responses.","status":"published","published":"2026-09-09T11:21:04Z","modified":"2026-10-08T15:25:57Z","cvss":[{"version":"4.0","score":7.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N","level":"high"}],"updated_at":"2026-11-02T17:27:28.564399Z"}],"ghsa":[{"id":"GHSA-rw58-wc66-99g4","title":"Duplicate Advisory: GitPython 3.1.59: --no-index bypasses diff unsafe-option protections and enables a blind local-file content oracle","description":"## Duplicate Advisory\n\nThis advisory has been withdrawn because it is a duplicate of GHSA-whh4-5q6c-9v3x. This link is maintained to preserve external references.\n\n## Original Description\nGitPython 3.1.59 fails to restrict the --no-index option in the high-level diff API, allowing attackers to read arbitrary filesystem paths as repository operands. Attackers can combine --no-index with -I/--ignore-matching-lines to create a content-dependent Boolean oracle, repeatedly querying local files to recover single-line secrets through distinguishable success or error responses.","status":"withdrawn","published":"2026-09-09T12:32:15Z","modified":"2026-09-30T23:28:16Z","cvss":[{"version":"4.0","score":7.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/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":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N","level":"medium"}],"cwes":["CWE-88"],"updated_at":"2026-11-02T14:41:23.783773Z"},{"id":"GHSA-whh4-5q6c-9v3x","title":"GitPython: --no-index bypasses diff unsafe-option protections and enables a blind local-file content oracle","description":"### Summary\n\nGitPython 3.1.59 blocks a previously available local-file read path through unsafe git diff options such as -O/--orderfile.\n\nHowever, the high-level diff API still permits --no-index with the default allow_unsafe_options=False.\n\n--no-index changes the semantics of the paths arguments: instead of repository-relative pathspecs, Git interprets them as arbitrary filesystem paths.\n\nWhen combined with the still-allowed -I/--ignore-matching-lines option, this creates a content-dependent Boolean oracle over a caller-selected local file.\n\nThis was reproduced against the published GitPython 3.1.59 wheel.\n\nThe original unsafe-option path is blocked in 3.1.59, while this alternate path remains reachable without setting allow_unsafe_options=True.\n\n### Details\n\nConfirmed API surface:\n\nrepo.index.diff(\n    None,\n    no_index=True,\n    I=pattern,\n    paths=[baseline_path, target_path],\n    create_patch=True,\n)\n\nThe relevant behavior is:\n\n1. --no-index makes the two values supplied via paths filesystem operands rather than repository pathspecs.\n2. -I/--ignore-matching-lines makes Git's result depend on whether the supplied regular expression matches the relevant file content.\n3. GitPython exposes the resulting bit through distinguishable behavior:\n   - matching condition: normal return with an empty DiffIndex\n   - non-matching condition: GitCommandError with exit status 1\n\nAn application that forwards attacker-influenced diff options and paths and exposes the success/error distinction can therefore be queried repeatedly to recover a guessable local single-line secret.\n\nThe issue was confirmed with the default allow_unsafe_options=False.\n\nThe behavior does not require the caller to explicitly opt into GitPython's unsafe-option mode.\n\nVerified intended security boundary:\n\n- GitPython 3.1.58 accepts the earlier -O/--orderfile local-file input path.\n- GitPython 3.1.59 rejects that same path with UnsafeOptionError.\n- GitPython 3.1.59 still permits the --no-index alternate path described above.\n\nThis appears to be an alternate route to the same local-file confidentiality property that the 3.1.59 diff option hardening is intended to protect.\n\n### PoC\n\nA minimal reproducer, controlled extraction demonstrator, proof matrix, and proposed remediation are included in the attached package.\n\n[gitpython-3159-maintainer-evidence.zip](https://github.com/user-attachments/files/31123571/gitpython-3159-maintainer-evidence.zip)\n\n\nThe minimal reproducer creates only temporary researcher-controlled files and demonstrates the following predicate:\n\ncorrect prefix   -\u003e normal GitPython return\nincorrect prefix -\u003e GitCommandError(status=1)\n\nIn the controlled extraction test, I generated three independent random single-line values and recovered all three exactly through repeated calls to the GitPython high-level API.\n\nResult: 3/3 recovered.\n\nThe extraction harness also installs a Python audit hook that rejects direct Python open() access to the target file during the oracle phase. The content-dependent read is therefore performed by the child git process invoked through GitPython rather than by the reproduction script directly.\n\nControls were also tested:\n\n- normal repository-scoped diff: no secret disclosure\n- same outside paths without --no-index: no arbitrary-filesystem interpretation\n- deliberately incorrect predicate: status 1 as expected\n\nSuggested remediation is to classify --no-index as unsafe for the high-level diff API unless the caller explicitly sets allow_unsafe_options=True.\n\n### Impact\n\nPotential impact is disclosure of local files readable by the process running GitPython.\n\nExploitation requires an embedding application to allow an attacker to influence:\n\n1. the relevant diff options,\n2. both path operands, and\n3. repeated requests while exposing a distinguishable success/error result.\n\nThe demonstrated attack is a blind content oracle rather than a one-request in-band file read. It is particularly applicable to short or structured single-line secrets where the target path and approximate value format are known or guessable.\n\nConfirmed affected release: GitPython 3.1.59.","status":"published","published":"2026-09-30T23:28:40Z","modified":"2026-09-30T23:28:41Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N","level":"medium"}],"cwes":["CWE-88","CWE-200"],"updated_at":"2026-11-02T14:41:23.783773Z"}],"nvd":[{"id":"CVE-2026-87818","description":"GitPython 3.1.59 fails to restrict the --no-index option in the high-level diff API, allowing attackers to read arbitrary filesystem paths as repository operands. Attackers can combine --no-index with -I/--ignore-matching-lines to create a content-dependent Boolean oracle, repeatedly querying local files to recover single-line secrets through distinguishable success or error responses.","status":"published","published":"2026-09-09T12:17:16.98Z","modified":"2026-09-16T15:12:45.633Z","cvss":[{"version":"4.0","score":7.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/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":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N","level":"medium","assessor":"secondary"}],"cwes":["CWE-88"],"updated_at":"2026-11-02T14:12:45.93749Z"}],"osv":[{"id":"CVE-2026-87818","title":"GitPython 3.1.59 Local File Content Oracle via --no-index","description":"GitPython 3.1.59 fails to restrict the --no-index option in the high-level diff API, allowing attackers to read arbitrary filesystem paths as repository operands. Attackers can combine --no-index with -I/--ignore-matching-lines to create a content-dependent Boolean oracle, repeatedly querying local files to recover single-line secrets through distinguishable success or error responses.","status":"published","published":"2026-09-09T11:21:04.681Z","modified":"2026-10-28T02:30:47.118073942Z","cvss":[{"version":"4.0","score":7.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N","level":"high"}],"cwes":["CWE-88"],"updated_at":"2026-11-02T15:45:19.210277Z"},{"id":"DEBIAN-CVE-2026-87818","description":"GitPython 3.1.59 fails to restrict the --no-index option in the high-level diff API, allowing attackers to read arbitrary filesystem paths as repository operands. Attackers can combine --no-index with -I/--ignore-matching-lines to create a content-dependent Boolean oracle, repeatedly querying local files to recover single-line secrets through distinguishable success or error responses.","status":"published","published":"2026-09-09T12:17:16.98Z","modified":"2026-10-31T14:00:10.419879449Z","cvss":[{"version":"4.0","score":7.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/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:46:05.506112Z"},{"id":"GHSA-rw58-wc66-99g4","title":"Duplicate Advisory: GitPython 3.1.59: --no-index bypasses diff unsafe-option protections and enables a blind local-file content oracle","description":"## Duplicate Advisory\n\nThis advisory has been withdrawn because it is a duplicate of GHSA-whh4-5q6c-9v3x. This link is maintained to preserve external references.\n\n## Original Description\nGitPython 3.1.59 fails to restrict the --no-index option in the high-level diff API, allowing attackers to read arbitrary filesystem paths as repository operands. Attackers can combine --no-index with -I/--ignore-matching-lines to create a content-dependent Boolean oracle, repeatedly querying local files to recover single-line secrets through distinguishable success or error responses.","status":"withdrawn","published":"2026-09-09T12:32:15Z","modified":"2026-09-30T23:45:04.071942879Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N","level":"medium"},{"version":"4.0","score":7.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/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-88"],"updated_at":"2026-11-02T15:46:56.281047Z"},{"id":"GHSA-whh4-5q6c-9v3x","title":"GitPython: --no-index bypasses diff unsafe-option protections and enables a blind local-file content oracle","description":"### Summary\n\nGitPython 3.1.59 blocks a previously available local-file read path through unsafe git diff options such as -O/--orderfile.\n\nHowever, the high-level diff API still permits --no-index with the default allow_unsafe_options=False.\n\n--no-index changes the semantics of the paths arguments: instead of repository-relative pathspecs, Git interprets them as arbitrary filesystem paths.\n\nWhen combined with the still-allowed -I/--ignore-matching-lines option, this creates a content-dependent Boolean oracle over a caller-selected local file.\n\nThis was reproduced against the published GitPython 3.1.59 wheel.\n\nThe original unsafe-option path is blocked in 3.1.59, while this alternate path remains reachable without setting allow_unsafe_options=True.\n\n### Details\n\nConfirmed API surface:\n\nrepo.index.diff(\n    None,\n    no_index=True,\n    I=pattern,\n    paths=[baseline_path, target_path],\n    create_patch=True,\n)\n\nThe relevant behavior is:\n\n1. --no-index makes the two values supplied via paths filesystem operands rather than repository pathspecs.\n2. -I/--ignore-matching-lines makes Git's result depend on whether the supplied regular expression matches the relevant file content.\n3. GitPython exposes the resulting bit through distinguishable behavior:\n   - matching condition: normal return with an empty DiffIndex\n   - non-matching condition: GitCommandError with exit status 1\n\nAn application that forwards attacker-influenced diff options and paths and exposes the success/error distinction can therefore be queried repeatedly to recover a guessable local single-line secret.\n\nThe issue was confirmed with the default allow_unsafe_options=False.\n\nThe behavior does not require the caller to explicitly opt into GitPython's unsafe-option mode.\n\nVerified intended security boundary:\n\n- GitPython 3.1.58 accepts the earlier -O/--orderfile local-file input path.\n- GitPython 3.1.59 rejects that same path with UnsafeOptionError.\n- GitPython 3.1.59 still permits the --no-index alternate path described above.\n\nThis appears to be an alternate route to the same local-file confidentiality property that the 3.1.59 diff option hardening is intended to protect.\n\n### PoC\n\nA minimal reproducer, controlled extraction demonstrator, proof matrix, and proposed remediation are included in the attached package.\n\n[gitpython-3159-maintainer-evidence.zip](https://github.com/user-attachments/files/31123571/gitpython-3159-maintainer-evidence.zip)\n\n\nThe minimal reproducer creates only temporary researcher-controlled files and demonstrates the following predicate:\n\ncorrect prefix   -\u003e normal GitPython return\nincorrect prefix -\u003e GitCommandError(status=1)\n\nIn the controlled extraction test, I generated three independent random single-line values and recovered all three exactly through repeated calls to the GitPython high-level API.\n\nResult: 3/3 recovered.\n\nThe extraction harness also installs a Python audit hook that rejects direct Python open() access to the target file during the oracle phase. The content-dependent read is therefore performed by the child git process invoked through GitPython rather than by the reproduction script directly.\n\nControls were also tested:\n\n- normal repository-scoped diff: no secret disclosure\n- same outside paths without --no-index: no arbitrary-filesystem interpretation\n- deliberately incorrect predicate: status 1 as expected\n\nSuggested remediation is to classify --no-index as unsafe for the high-level diff API unless the caller explicitly sets allow_unsafe_options=True.\n\n### Impact\n\nPotential impact is disclosure of local files readable by the process running GitPython.\n\nExploitation requires an embedding application to allow an attacker to influence:\n\n1. the relevant diff options,\n2. both path operands, and\n3. repeated requests while exposing a distinguishable success/error result.\n\nThe demonstrated attack is a blind content oracle rather than a one-request in-band file read. It is particularly applicable to short or structured single-line secrets where the target path and approximate value format are known or guessable.\n\nConfirmed affected release: GitPython 3.1.59.","status":"published","published":"2026-09-30T23:28:40Z","modified":"2026-10-01T17:26:00.195974026Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N","level":"medium"}],"cwes":["CWE-200","CWE-88"],"updated_at":"2026-11-02T15:46:58.767335Z"},{"id":"OESA-2026-4025","title":"python-GitPython security update","description":"**GitPython*is a python library used to interact with Git repositories.GitPython provides object model read and write access to your git repository. Access repository information conveniently, alter the index directly, handle remotes, or go down to low-level object database access with big-files support.With the new object database abstraction added in 0.3, its even possible to implement your own storage mechanisms, the currently available implementations are \u0026amp;apos;cgit\u0026amp;apos; and pure python, which is the default.Documentation The latest documentation can be found here: As this version of GitPython depends on GitDB, which in turn needs smmap to work, installation is a bit more involved if you do a manual installation, instead of using pip.\r\n\r\nSecurity Fix(es):\n\nGitPython before 3.1.60 fails to properly validate the git directory location, allowing attackers to impersonate the git directory using tracked files like gitdir, commondir, and HEAD. Attackers can execute arbitrary code by placing a malicious pre-commit hook in the tracked hooks directory that executes when a victim calls index.commit() on a cloned or opened repository.(CVE-2026-87817)\n\nGitPython 3.1.59 fails to restrict the --no-index option in the high-level diff API, allowing attackers to read arbitrary filesystem paths as repository operands. Attackers can combine --no-index with -I/--ignore-matching-lines to create a content-dependent Boolean oracle, repeatedly querying local files to recover single-line secrets through distinguishable success or error responses.(CVE-2026-87818)\n\nGitPython before 3.1.60 contains a regular expression denial of service vulnerability in Actor.name_email_regex that processes commit author and committer fields. Attackers can craft a commit object with a malformed author field containing an unterminated angle bracket to cause quadratic backtracking, exhausting CPU resources for over two minutes per commit access.(CVE-2026-87819)","status":"published","published":"2026-09-25T01:27:26Z","modified":"2026-09-25T01:45:05.595929548Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T15:52:47.643553Z"},{"id":"OESA-2026-4026","title":"python-GitPython security update","description":"**GitPython*is a python library used to interact with Git repositories.GitPython provides object model read and write access to your git repository. Access repository information conveniently, alter the index directly, handle remotes, or go down to low-level object database access with big-files support.With the new object database abstraction added in 0.3, its even possible to implement your own storage mechanisms, the currently available implementations are \u0026amp;apos;cgit\u0026amp;apos; and pure python, which is the default.Documentation The latest documentation can be found here: As this version of GitPython depends on GitDB, which in turn needs smmap to work, installation is a bit more involved if you do a manual installation, instead of using pip.\r\n\r\nSecurity Fix(es):\n\nGitPython before 3.1.60 fails to properly validate the git directory location, allowing attackers to impersonate the git directory using tracked files like gitdir, commondir, and HEAD. Attackers can execute arbitrary code by placing a malicious pre-commit hook in the tracked hooks directory that executes when a victim calls index.commit() on a cloned or opened repository.(CVE-2026-87817)\n\nGitPython 3.1.59 fails to restrict the --no-index option in the high-level diff API, allowing attackers to read arbitrary filesystem paths as repository operands. Attackers can combine --no-index with -I/--ignore-matching-lines to create a content-dependent Boolean oracle, repeatedly querying local files to recover single-line secrets through distinguishable success or error responses.(CVE-2026-87818)\n\nGitPython before 3.1.60 contains a regular expression denial of service vulnerability in Actor.name_email_regex that processes commit author and committer fields. Attackers can craft a commit object with a malformed author field containing an unterminated angle bracket to cause quadratic backtracking, exhausting CPU resources for over two minutes per commit access.(CVE-2026-87819)","status":"published","published":"2026-09-25T01:27:26Z","modified":"2026-09-25T01:45:04.66251923Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T15:52:47.643553Z"},{"id":"OESA-2026-4027","title":"python-GitPython security update","description":"**GitPython*is a python library used to interact with Git repositories.GitPython provides object model read and write access to your git repository. Access repository information conveniently, alter the index directly, handle remotes, or go down to low-level object database access with big-files support.With the new object database abstraction added in 0.3, its even possible to implement your own storage mechanisms, the currently available implementations are \u0026amp;apos;cgit\u0026amp;apos; and pure python, which is the default.Documentation The latest documentation can be found here: As this version of GitPython depends on GitDB, which in turn needs smmap to work, installation is a bit more involved if you do a manual installation, instead of using pip.\r\n\r\nSecurity Fix(es):\n\nGitPython before 3.1.60 fails to properly validate the git directory location, allowing attackers to impersonate the git directory using tracked files like gitdir, commondir, and HEAD. Attackers can execute arbitrary code by placing a malicious pre-commit hook in the tracked hooks directory that executes when a victim calls index.commit() on a cloned or opened repository.(CVE-2026-87817)\n\nGitPython 3.1.59 fails to restrict the --no-index option in the high-level diff API, allowing attackers to read arbitrary filesystem paths as repository operands. Attackers can combine --no-index with -I/--ignore-matching-lines to create a content-dependent Boolean oracle, repeatedly querying local files to recover single-line secrets through distinguishable success or error responses.(CVE-2026-87818)\n\nGitPython before 3.1.60 contains a regular expression denial of service vulnerability in Actor.name_email_regex that processes commit author and committer fields. Attackers can craft a commit object with a malformed author field containing an unterminated angle bracket to cause quadratic backtracking, exhausting CPU resources for over two minutes per commit access.(CVE-2026-87819)","status":"published","published":"2026-09-25T01:27:27Z","modified":"2026-09-25T01:45:06.501047866Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T15:52:47.643553Z"},{"id":"PYSEC-2026-3983","description":"GitPython 3.1.59 fails to restrict the --no-index option in the high-level diff API, allowing attackers to read arbitrary filesystem paths as repository operands. Attackers can combine --no-index with -I/--ignore-matching-lines to create a content-dependent Boolean oracle, repeatedly querying local files to recover single-line secrets through distinguishable success or error responses.","status":"withdrawn","published":"2026-09-09T12:17:16.98Z","modified":"2026-10-01T17:15:02.515704536Z","cvss":[{"version":"4.0","score":7.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/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:57.255153Z"},{"id":"UBUNTU-CVE-2026-87818","description":"GitPython 3.1.59 fails to restrict the --no-index option in the high-level diff API, allowing attackers to read arbitrary filesystem paths as repository operands. Attackers can combine --no-index with -I/--ignore-matching-lines to create a content-dependent Boolean oracle, repeatedly querying local files to recover single-line secrets through distinguishable success or error responses.","status":"published","published":"2026-09-09T12:17:00Z","modified":"2026-09-16T14:03:37.663938671Z","cvss":[{"version":"3.1","score":6.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N","level":"medium"},{"version":"4.0","score":7.1,"vector":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N","level":"high"}],"updated_at":"2026-11-02T16:57:24.828975Z"},{"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":"SUSE-SU-2026:4191-1","title":"Security update for python-GitPython","description":"This update for python-GitPython fixes the following issues:\n\n- CVE-2026-87817: failure to properly validade the git directory location allows attackers to\n  impersonate the git directory using tracked files and execute arbitrary code by placing pre-commit hooks in the\n  tracked hooks directory (bsc#1279905).\n- CVE-2026-87818: failure to restrict the `--no-index` option in the high-level diff API allows\n  attackers to read arbitrary filesystem paths as repository operands and create content-dependent Boolean oracles\n  (bsc#1279906).\n- CVE-2026-87819: quadratic backtracking in the `Actor.name_email_regex` regular expression allows\n  attackers to cause CPU exhaustion and a DoS via a commit with a malformed author field (bsc#1279907).\n","status":"published","published":"2026-09-15T12:36:08Z","modified":"2026-09-16T10:00:05.693246336Z","updated_at":"2026-11-02T15:54:05.392906Z"}]}}
