CVE-2026-78679: GitPython before 3.1.59 Arbitrary File Read via TagReference.create

Published Aug 25, 2026
·
Updated

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 unsafegittagoptions = ["--file","-F"] and a guard call, but the guard is Git.checkunsafeoptions(options=Git.optioncandidates([], kwargs), unsafeoptions=...) 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 allowunsafeoptions=False.

Proof of Concept python from git import TagReference t = TagReference.create(repo, "vpwn", reference="--file=/home/app/.ssh/idrsa") 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/idrsa". 2. Check: Git.checkunsafeoptions(optioncandidates([], kwargs), ["--file","-F"]) @ tag.py:137-141. Guard: denylist includes --file/-F. Bypass proof: optioncandidates 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 allowunsafeoptions=False): TagReference.create(repo,'vp','--file=<secret>') → PASSED; tag.message == 'GATESECRETLINEA\nGATESECRETLINEB'. Control: TagReference.create(..., file='<secret>') → UnsafeOptionError: --file is not allowed. Fix-commit read: 3af0c251 adds optioncandidates([], 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 checkunsafeoptions, or place a -- separator before the positional arguments in TagReference.create().

--- Reported by zx (Jace) — GitHub: @manus-use

Other sources

GitPython before 3.1.59 contains an arbitrary file read vulnerability in TagReference.create() where a positional reference parameter bypasses the unsafe option guard. Attackers can supply a reference value like --file=<path> to read arbitrary files, with contents returned in the annotated tag message.

— MITRE

Affected Software

2 affected componentsFixes available
GitPython GitPython<3.1.59
pip/GitPython<=3.1.58
3.1.59

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade pip/GitPython to a version that resolves this vulnerability.

    Fixed in 3.1.59
  2. Upgrade

    Upgrade GitPython to a version that resolves this vulnerability.

    Fixed in 3.1.59
  3. Configuration

    Adjust TagReference.create so the guard call inspects the actual user-influenced positional arguments (reference/path). Concretely, change the guard input from an empty args list to include positionals (e.g., pass the positional reference/path into _option_candidates) or ensure git tag receives a '--' separator before any positional reference so that '--file' cannot be interpreted as an option.

    TagReference.create (git/refs/tag.py) Unsafe option guard = Include positional reference/path in unsafe option candidate list (args) or insert '--' separator before positional args

Event History

Aug 25, 2026
CVE Published
via MITRE·01:30 AM
Data Sourced
via MITRE·01:30 AM
DescriptionSeverityWeakness
Data Sourced
via NVD·02:16 AM
DescriptionSeverityWeakness
Sep 8, 2026
Advisory Published
via GitHub·07:42 PM
Data Sourced
via GitHub·07:42 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

Who can exploit this issue?

An attacker needs privileges to invoke application functionality that calls TagReference.create() and control its positional reference argument. The supplied CVSS vector indicates network reachability, low attack complexity, no user interaction, and low privileges required.

2

Are default GitPython installations affected?

The issue is in TagReference.create() before version 3.1.59, but the provided data does not establish whether any particular application uses that method or exposes attacker-controlled reference values by default.

3

What is the impact if exploitation succeeds?

An attacker can provide a value such as --file=<path> and cause arbitrary file contents to be included in an annotated tag message. The stated impact is high confidentiality impact, with no integrity or availability impact.

4

What can be done if upgrading is not immediately possible?

Do not allow untrusted users to control the positional reference parameter passed to TagReference.create(). Reject option-like reference values, particularly values beginning with -- and values using --file=<path>.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203