Sep 8, 2026·5 min read·4 visits
GitPython prior to version 3.1.59 fails to validate positional parameters in TagReference.create(), enabling command-line option injection (like --file) that allows attackers to perform arbitrary file reads.
A command-line option injection vulnerability in GitPython allows low-privilege or unauthenticated actors to read arbitrary local files. The flaw resides in the TagReference.create() function, which fails to evaluate positional arguments against the library's unsafe-option denylist, enabling the execution of native git commands with injected option flags.
GitPython is a popular Python library used to interact with Git repositories by wrapping the native git command-line interface. When developers invoke high-level API functions such as TagReference.create(), GitPython processes these calls into structured arguments and executes a git subprocess. The security boundary of GitPython relies on the assumption that arbitrary user input cannot alter the execution context of the underlying git binary.\n\nTo prevent command injection and option injection, GitPython implements a validation component called Git.check_unsafe_options(). This mechanism evaluates provided flags against a predefined denylist of dangerous options (e.g., --file or -F for git-tag), which could read or write external files. If a forbidden option is identified, the library raises an UnsafeOptionError exception to prevent execution.\n\nThe vulnerability CVE-2026-78679 exists because the invocation of this validation mechanism in the tagging module completely bypassed positional arguments. Because GitPython does not append a double-dash (--) separator to isolate options from positional inputs during command synthesis, the underlying git command-line parser treats positional values starting with a hyphen as options. This logical oversight permits an attacker to perform unauthorized out-of-band file read operations.
The core defect resides within the create method of the TagReference class inside git/refs/tag.py. When a developer executes TagReference.create(), the method processes multiple arguments: repo, path, reference, and any additional keyword arguments passed via **kwargs. To ensure safety, the function relies on Git.check_unsafe_options(), which in turn calls Git._option_candidates() to extract potential option strings for scanning.\n\nIn the vulnerable implementation, the invocation was structured as Git._option_candidates([], kwargs). The first argument of _option_candidates is designed to receive a list of positional arguments, while the second processes keyword arguments. By passing an empty list ([]) as the first argument, GitPython's validation system only evaluated keys and values found inside the kwargs dictionary.\n\nConsequently, the positional arguments path and reference were never processed by the validation routine. When a caller passes a value starting with a hyphen (such as --file=/etc/passwd) as the reference argument, it completely evades the check. The resulting system call compiles these arguments directly into a shell-less command array, causing native git to interpret the injected positional argument as an option flag.
Analyzing the implementation details highlights how the validation bypass was constructed and subsequently corrected. In vulnerable versions of GitPython, the validation bypass occurred directly before the command execution phase because of the incorrect array passing.\n\nBelow is a comparative breakdown of the vulnerable code and the official patch introduced in commit 1b0d2d9b91575f7db44ef4ff58ac37fc9335e5f6:\n\npython\n# VULNERABLE CODE PATH (git/refs/tag.py)\ndef create(cls, repo, path, reference=\"HEAD\", force=False, ... allow_unsafe_options=False, **kwargs):\n # ...\n if not allow_unsafe_options:\n # BUG: Passing empty list [] ignores the positional parameters 'path' and 'reference'\n Git.check_unsafe_options(\n options=Git._option_candidates([], kwargs),\n unsafe_options=cls.unsafe_git_tag_options,\n clusterable_short_options=\"46adefilnqsv\",\n )\n # ...\n\n\nThe patch resolves the logical flaw by explicitly adding path and reference to the list of candidates passed to _option_candidates(). This ensures that even when user input is mapped to positional arguments, it is analyzed prior to subcommand construction.\n\npython\n# PATCHED CODE PATH (git/refs/tag.py)\ndef create(cls, repo, path, reference=\"HEAD\", force=False, ... allow_unsafe_options=False, **kwargs):\n # ...\n legacy_ref = kwargs.pop(\"ref\", None)\n if legacy_ref:\n reference = legacy_ref\n\n if not allow_unsafe_options:\n # FIX: 'path' and 'reference' are now passed in the candidates list\n Git.check_unsafe_options(\n options=Git._option_candidates([path, reference], kwargs),\n unsafe_options=cls.unsafe_git_tag_options,\n clusterable_short_options=\"46adefilnqsv\",\n )\n # ...\n\n\nBy incorporating the positional parameters, any input starting with a hyphen in either path or reference is subjected to the same denylist matching as standard keyword arguments. This prevents the execution pipeline from accepting external options under the guise of positional operands.
Exploiting this vulnerability requires that an application exposes the path or reference parameters of TagReference.create() to user-controlled inputs. When this condition is met, an attacker can specify a value designed to act as a Git option. For example, setting the reference parameter to --file=/etc/passwd triggers the flaw.\n\nmermaid\ngraph LR\n A[\"User Input: reference = '--file=/etc/passwd'\"] --> B[\"TagReference.create() called\"]\n B --> C{\"Is input in kwargs?\"}\n C -- \"No, it is positional\" --> D[\"Bypasses check_unsafe_options()\"]\n C -- \"Yes\" --> E[\"Blocked by check_unsafe_options()\"]\n D --> F[\"Git Command execution: git tag tag_name --file=/etc/passwd\"]\n F --> G[\"Git reads /etc/passwd as tag annotation message\"]\n G --> H[\"Attacker reads tag metadata to exfiltrate file content\"]\n\n\nDuring subprocess execution, the native git CLI processes the options sequentially. The presence of --file=/etc/passwd instructs the git tag command to read the target file's contents from disk and embed them as the annotation message for the newly generated tag. Since the command executes under the privileges of the Python application process, it can read any file the application has permission to access.\n\nOnce the tag is created, the attacker retrieves the contents of the target file by querying the tag's metadata. In GitPython, this is accomplished by reading the message property of the returned TagReference or by issuing a git show command on the repository. This represents a highly reliable out-of-band data exfiltration channel.
The primary remediation for CVE-2026-78679 is upgrading the GitPython library to version 3.1.59 or later. This release updates all reference creation utilities to evaluate positional parameters, thereby closing the command-line option injection pathway. Organizations should review their dependency manifests and update their environments immediately.\n\nIn environments where upgrading the library is not immediately feasible, developers must implement strict input validation on all parameters passed to GitPython APIs. Any user-controlled value destined for GitPython must be validated to ensure it does not start with a hyphen character (-), which is the universal prefix for command-line options.\n\nAdditionally, implementing input filtering using a whitelist of allowed characters (such as alphanumeric characters, dashes, and underscores) represents an effective defense-in-depth strategy. Developers should also verify that the underlying execution environment enforces least-privilege principles, limiting the files accessible to the application worker processes in the event of an exploitation attempt.
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| Product | Affected Versions | Fixed Version |
|---|---|---|
GitPython gitpython-developers | >= 3.1.33, < 3.1.59 | 3.1.59 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-73 |
| Attack Vector | Network (AV:N) |
| CVSS v4.0 Score | 7.1 |
| EPSS Score | 0.00241 |
| Impact | Arbitrary File Read / Information Disclosure |
| Exploit Status | Proof-of-Concept (PoC) |
| KEV Status | Not Listed |
The software allows user input to control or influence paths or file names passed to file system APIs without sufficient validation.
A Denial of Service (DoS) vulnerability exists in the xmldom library when parsing HTML-mode documents with mixed-case closing tags for raw-text or escapable raw-text elements like script, style, textarea, or title. This leads to algorithmic complexity issues and quadratic output amplification during DOM serialization.
GitPython prior to version 3.1.59 contains a path traversal vulnerability via parameter injection. The clone denylist did not restrict the `--separate-git-dir` option, allowing attackers to write repository metadata to arbitrary system paths.
CVE-2026-72925 is a critical vulnerability in the SWC HTML minifier (@swc/html and swc_html_minifier) where safe Unicode-escaped characters in embedded JSON script tags are normalized into raw, unescaped characters during optimization, causing browser-side HTML injection and Cross-Site Scripting.
A critical logical flaw in the Natural Language Toolkit (NLTK) allows attackers to bypass the application-level directory sandbox. This vulnerability enables unauthenticated directory enumeration and arbitrary local file or SQLite database access.
An improper integrity verification vulnerability exists in the Natural Language Toolkit (NLTK) library up to and including version 3.9.4. The library's download utility writes remote ZIP packages directly to disk and extracts their contents onto the filesystem before executing cryptographic checksum validation. An attacker capable of intercepting or manipulating the download stream can exploit this behavior to perform arbitrary file writes, directory traversal, or execute untrusted serialized content.
A critical Server-Side Request Forgery (SSRF) bypass vulnerability exists in CodeWhale before version 0.8.64 (and version 0.8.41 in the 0.8.x branch) due to a Time-of-Check to Time-of-Use (TOCTOU) bug in its DNS pre-flight validation mechanism. By returning a temporary resolution failure during validation and subsequently resolving to restricted IPs during HTTP execution, attackers can bypass security rules.