Skip to content

Bump GitPython to 3.1.59 for CVE-2026-78679 - #33

Merged
Arun Iyer (aruniyer) merged 2 commits into
mainfrom
copilot/fix-gitpython-tagreference-bypass
Sep 18, 2026
Merged

Arun Iyer (aruniyer) merged 2 commits into
mainfrom
copilot/fix-gitpython-tagreference-bypass

Conversation

Copilot AI commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

GitPython 3.1.58 is vulnerable to GHSA-3wxw-xv34-2frg / CVE-2026-78679, where TagReference.create() can accept unsafe positional reference values that bypass the --file guard and may allow arbitrary local file reads. This PR updates the direct dependency pin to the lowest patched release.

  • Dependency update

    • Bumps GitPython in requirements.txt:
      -GitPython==3.1.58
      +GitPython==3.1.59
  • Reachability assessment

    • Searched for TagReference, TagReference.create, git.refs.tag, and broad GitPython import/call patterns.
    • No usage of the affected TagReference.create() API was found.
    • Existing GitPython usage appears limited to repository clone/init/index/reset operations.
    • Assessment: not currently reachable; update is primarily to satisfy vulnerability scanning.
    • Confidence: high, because the advisory names a specific API and matching usage was not found.
Original prompt

This section details the Dependabot vulnerability alert you should resolve

<alert_title>GitPython: TagReference.create positional reference bypasses kwargs-only --file guard, enabling arbitrary file read (incomplete fix of 3af0c251)</alert_title>
<alert_description>## Summary
TagReference.create() forwards a caller-influenced positional reference value into git tag without it ever being inspected by the unsafe-option guard, allowing an arbitrary file read (the file's contents are returned in-band as the annotated tag message). This is an incomplete-fix bypass of commit 3af0c251 (the fix for GHSA-3f7w-8rr8-f37f's tag instance).

Root Cause

The fix 3af0c251 added unsafe_git_tag_options = ["--file","-F"] and a guard call, but the guard is Git.check_unsafe_options(options=Git._option_candidates([], kwargs), unsafe_options=...) at git/refs/tag.py:139 — it passes an EMPTY args list and inspects kwargs only. The dangerous values path and reference are POSITIONALS (args = (path, reference), tag.py:156), placed before any --. A user-influenced reference="--file=<path>" therefore reaches git tag as the exact --file option the fix intended to block, creating an annotated tag whose message is the file's contents.

Impact

Arbitrary local file read at the privileges of the host process; contents returned in-band via tagref.tag.message. Requires the embedding application to forward a caller-influenced reference value into TagReference.create() (pure VALUE control — the CVE-2026-42215 threat model). Default allow_unsafe_options=False.

Proof of Concept

from git import TagReference
t = TagReference.create(repo, "vpwn", reference="--file=/home/app/.ssh/id_rsa")
print(t.tag.message)   # contents of the file

Attack Chain

  1. Entry: app calls TagReference.create(repo, name, reference=<user>) with reference="--file=/home/app/.ssh/id_rsa".
  2. Check: Git.check_unsafe_options(_option_candidates([], kwargs), ["--file","-F"]) @ tag.py:137-141. Guard: denylist includes --file/-F. Bypass proof: _option_candidates receives args=[] → the positional reference is never a candidate (the kwarg spelling file="…" IS blocked; only the positional escapes).
  3. Sink: repo.git.tag(*args, **kwargs) @ tag.py:158 → no --. argv (observed): ['git','tag','-f','vpwn','--file=<secret>'].
  4. Impact: annotated tag created; tagref.tag.message == file contents (arbitrary file read).

Bypass Evidence

Independently reproduced (independent test harness, git 2.43.0, default allow_unsafe_options=False): TagReference.create(repo,'vp','--file=<secret>') → PASSED; tag.message == 'GATE_SECRET_LINE_A\nGATE_SECRET_LINE_B'. Control: TagReference.create(..., file='<secret>')UnsafeOptionError: --file is not allowed. Fix-commit read: 3af0c251 adds _option_candidates([], kwargs) (empty args → positional never a candidate).

Affected Versions

GitPython <= 3.1.58 (sink present verbatim on the latest release tag; git diff 3.1.57..HEAD touches only test files).

Suggested Fix

Include the positional reference (and path) in the option-candidate list passed to check_unsafe_options, or place a -- separator before the positional arguments in TagReference.create().


Reported by zx (Jace) — GitHub: Jace (@manus-use)</alert_description>

moderate
GHSA-3wxw-xv34-2frg, CVE-2026-78679
GitPython
pip
<vulnerable_versions>= 3.1.58</vulnerable_versions>
<patched_version>3.1.59</patched_version>
<manifest_path>requirements.txt</manifest_path>

https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-3wxw-xv34-2frg https://nvd.nist.gov/vuln/detail/CVE-2026-78679 https://github.com/gitpython-developers/GitPython/pull/2208 https://github.com/gitpython-developers/GitPython/commit/1b0d2d9b91575f7db44ef4ff58ac37fc9335e5f6 https://github.com/gitpython-developers/GitPython/releases/tag/3.1.59 https://www.vulncheck.com/advisories/gitpython-before-arbitrary-file-read-via-tagreference-create https://github.com/advisories/GHSA-3wxw-xv34-2frg

<task_instructions>Resolve this alert by updating the affected package to a non-vulnerable version. Prefer the lowest non-vulnerable version (see the patched_version field above) over the latest to minimize breaking changes. Include a Reachability Assessment section in the PR description. Review the alert_description field to understand which APIs, features, or configurations are affected, then search the codebase for usage of those specific items. If the vulnerable code path is reachable, explain how (which files, APIs, or call sites use the affected functionality) and note that the codebase is actively exposed to this vulnerability. If the vulnerable code path is not reachable, explain why (e.g. the affected API i...

  • Resolves microsoft/repoclassbench alert #79

Co-authored-by: aruniyer <429556+aruniyer@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix GitPython TagReference positional reference bypass issue Bump GitPython to 3.1.59 for CVE-2026-78679 Sep 18, 2026
@aruniyer
Arun Iyer (aruniyer) marked this pull request as ready for review September 18, 2026 09:10
@aruniyer
Arun Iyer (aruniyer) merged commit be8bfcf into main Sep 18, 2026
4 checks passed
@aruniyer
Arun Iyer (aruniyer) deleted the copilot/fix-gitpython-tagreference-bypass branch September 18, 2026 09:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants