Apr 27, 2026·7 min read·93 visits
GitPython < 3.1.45 fails to properly filter dangerous Git options when supplied via Python keyword arguments. Attackers can bypass security checks by using underscores instead of hyphens (e.g., `upload_pack` instead of `upload-pack`), resulting in arbitrary remote code execution via the underlying Git executable.
GitPython versions prior to 3.1.45 are vulnerable to a command injection flaw due to an architectural logic error in how keyword arguments are sanitized. The library attempts to block dangerous Git options like `--upload-pack` but performs this validation before applying Pythonic underscore-to-hyphen normalization. This allows attackers to bypass the blocklist using underscore-formatted arguments, leading to arbitrary command execution when the underlying Git binary is invoked.
GitPython is a Python library used to interact with Git repositories, providing an object-oriented wrapper around the underlying Git command-line interface. Developers frequently use this library to programmatically clone, fetch, pull, and manipulate repositories. The vulnerability, identified as GHSA-RPM5-65CW-6HJ4, exists within the parameter processing pipeline where Python keyword arguments are translated into Git command-line options.
To bridge Python conventions and POSIX command-line flags, GitPython allows developers to pass keyword arguments (kwargs) using underscores, which the library automatically normalizes into hyphens. For example, passing upload_pack='...' in Python translates to --upload-pack='...' at the command line. This normalization is a core feature designed to maintain Python code readability while adhering to Git's expected argument syntax.
GitPython maintains a security blocklist to prevent the injection of dangerous Git options that natively support command execution, such as --upload-pack, --receive-pack, and --extcmd. The vulnerability occurs because the library executes this security validation step before performing the underscore-to-hyphen normalization. Consequently, an attacker can supply the dangerous arguments in their pre-normalized underscore form to bypass the security filter entirely.
Once the validation step completes successfully, GitPython normalizes the malicious keyword argument and passes the hyphenated flag to the Git subprocess. This results in the execution of arbitrary operating system commands with the privileges of the Python process invoking the Git wrapper.
The root cause of GHSA-RPM5-65CW-6HJ4 is an architectural sequencing error in the input sanitization pipeline. Effective input validation mandates that data must be normalized to its final, canonical representation before any security checks are applied. GitPython violates this principle by evaluating the input in its raw form rather than its normalized execution form.
When a developer invokes a Git command via the GitPython API, the library packages the provided keyword arguments into a dictionary. The security function iterates over the keys in this dictionary, checking against a hardcoded list of restricted strings. The blocklist specifically contains the standard Git command-line formats, specifically upload-pack, receive-pack, and extcmd.
If the dictionary key is provided as upload_pack, the string comparison against the blocklist fails, and the security check permits the argument. Following this validation, the library's command builder processes the dictionary to construct the actual shell command string. During this phase, it replaces all underscores in the dictionary keys with hyphens to match Git's parameter requirements.
The normalized dictionary keys are then concatenated with their respective values and appended to the Git binary path. The resulting command array is passed to Python's subprocess execution module. By processing the validation phase prematurely, GitPython guarantees that the command builder will subsequently mutate the validated input into an unsafe state, completely nullifying the intended security controls.
Understanding the vulnerability requires analyzing the exact data flow of the keyword arguments. The flaw exists in the method responsible for transforming the **kwargs dictionary into the final list of arguments passed to the subprocess.Popen call.
The implementation flaw is evident in the execution order. The Python dictionary {'upload_pack': 'touch /tmp/pwned'} is passed to the validation routine. The routine checks for the literal string upload-pack. Since upload_pack (with an underscore) does not match upload-pack (with a hyphen), no exception is raised.
After the validation loop completes, a separate processing loop handles the command string assembly. This loop takes upload_pack, runs a string replace operation for underscores, and yields --upload-pack. It then appends the provided value, resulting in --upload-pack=touch /tmp/pwned.
The patch for this vulnerability involves shifting the validation logic to occur after the normalization step, or explicitly checking both the underscore and hyphenated variations of the dangerous parameters. By normalizing the dictionary keys to their canonical hyphenated state first, the security check correctly identifies the prohibited arguments regardless of how they were initially formatted in the Python code.
Exploitation of this vulnerability requires the application using GitPython to accept user-controlled input and apply it as a keyword argument to a Git command execution function. This pattern is increasingly common in automated CI/CD pipelines, repository management tools, and "agentic" AI systems that dynamically generate operational commands based on user prompts.
An attacker crafts a malicious payload targeting a remote Git operation, such as clone, fetch, pull, or push. The payload specifies the upload_pack argument, utilizing the underscore format to ensure the application processes it without triggering the built-in GitPython exception. The value of this argument contains the actual operating system commands the attacker wishes to execute.
import git
# The attacker controls this input variable via a web form or API endpoint
dangerous_option = "touch /tmp/pwned"
repo = git.Repo.init("/tmp/test-repo")
# The developer passes the user input as a keyword argument
# The underscore bypasses the GitPython security blocklist
repo.git.fetch(upload_pack=dangerous_option)When the vulnerable application processes this code, GitPython constructs and executes the command git fetch --upload-pack='touch /tmp/pwned'. The git fetch operation natively supports the --upload-pack parameter to specify the path to the git-upload-pack binary on the remote end. However, Git executes the provided string as a shell command to initialize the pack transfer, resulting in immediate arbitrary code execution on the local host processing the fetch request.
The vulnerability enables arbitrary OS command execution, representing a critical risk to systems utilizing vulnerable versions of GitPython. The injected commands execute with the identical permissions and environment variables of the Python application hosting the GitPython library.
In environments where GitPython operates as part of a backend web service or API, successful exploitation yields a full remote shell or direct access to the underlying filesystem. Attackers can leverage this foothold to exfiltrate sensitive data, manipulate internal databases, or extract environment variables containing secondary authentication tokens, such as AWS credentials or database passwords.
This vulnerability is particularly consequential for AI-driven development tools and automated repository management systems. These platforms frequently parse user instructions or arbitrary repository data and map them into dynamically constructed Git commands. If these inputs dictate the keyword arguments passed to the GitPython wrapper, the system is immediately vulnerable to complete compromise without requiring authentication bypasses in the primary web application.
The definitive remediation for this vulnerability is upgrading GitPython to version 3.1.45 or later. The patched release restructures the validation logic to accurately identify and block dangerous Git options, even when they are supplied using Python's underscore-based keyword argument syntax. Organizations should update dependencies via pip, poetry, or their respective package managers immediately.
If upgrading is not operationally feasible in the short term, developers must implement strict input validation at the application layer. Before passing any dynamic dictionary or user-controlled input to GitPython via **kwargs, the application must manually inspect all keys. Any keys matching upload_pack, receive_pack, extcmd, or their hyphenated equivalents must be explicitly rejected.
Furthermore, developers should adopt a strict allowlist approach when mapping untrusted data to system command interfaces. Avoid dynamically expanding untrusted dictionaries directly into function calls. Instead, map specific, expected user inputs to hardcoded arguments within the application logic, ensuring that arbitrary Git options cannot be introduced into the command pipeline regardless of library-level validation failures.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
GitPython gitpython-developers | < 3.1.45 | 3.1.45 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-78: Improper Neutralization of Special Elements used in an OS Command |
| Attack Vector | Network / Context Dependent |
| Impact | Remote Code Execution (RCE) |
| CVSS Score | 8.8 (Estimated) |
| Exploit Status | Proof of Concept Available |
| Vulnerable Component | Git command wrappers (`repo.git.*`) |
The software constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command when it is sent to a downstream component.
CVE-2026-115895 is a high-severity code injection vulnerability (CWE-94) in the happy-dom npm package prior to version 21.0.4. The vulnerability exists within the ECMAScriptModuleCompiler component, which transforms ECMAScript module syntax into executable Node.js functions when JavaScript evaluation is enabled. Due to an incomplete fix for CVE-2026-33943, the compiler failed to validate local named import aliases against legal JavaScript identifier rules. Attackers supplying crafted module imports—specifically utilizing destructuring default initializers alongside JSON module attributes—can inject arbitrary JavaScript expressions directly into the host Node.js runtime context.
An improper input validation and authorization bypass vulnerability exists in the LangGraph storage layer affecting langgraph, langgraph-checkpoint-postgres, and langgraph-checkpoint-sqlite. Because relational store implementations serialize namespace tuples into dot-delimited strings without validating labels on read, search, delete, and batch operations, an attacker who controls a namespace label can inject periods (.) to traverse namespace boundaries and access, modify, or delete data belonging to other namespaces.
CVE-2026-115886 (GHSA-2wqp-q3c6-ccj5) is a Server-Side Request Forgery (SSRF) and Unsafe Reflection vulnerability in MLflow versions 3.12.0rc0 prior to 3.17.0. Unauthenticated REST API endpoints accept serialized third-party scorer JSON payloads that are dynamically deserialized and reflectively instantiated without sanitizing constructor keyword arguments. When optional dependencies such as trulens and trulens-providers-litellm are installed, attackers can inject egress-steering arguments into the scorer payload, forcing the MLflow server to dispatch outbound HTTP requests to arbitrary internal destinations or cloud metadata services.
CVE-2026-113872 (GHSA-q7qp-rjg7-q26m) is a high-severity denial-of-service vulnerability affecting the multer multipart/form-data upload middleware for Node.js and Express in versions 2.0.0 through 2.4.0. When an endpoint is configured to accept multiple files using an asynchronous fileFilter callback, a crafted, truncated multipart HTTP request can trigger an unhandled error event on the underlying busboy stream parser after request teardown has already completed. Because all error listeners are stripped during teardown, Node.js treats the resulting error event as an uncaught exception and immediately terminates the server process.
CVE-2026-115897 (also tracked as GHSA-m5mm-p8h7-m29v and aliased as CVE-2026-115754) is a Cross-Site Scripting (XSS) vulnerability in the Yahoo serialize-javascript npm package prior to version 7.1.3. The flaw exists in the regular expression used by escapeFunctionBody() to neutralize HTML script closing tags within serialized JavaScript functions. Because function bodies are sanitized in isolation before structural formatting is applied, a function whose string representation terminates directly with the sequence '</script' bypasses the positive lookahead check. When combined with serialization formatting options that introduce whitespace delimiters and a subsequent property that supplies a closing bracket, an attacker can prematurely terminate an enclosing HTML <script> block and inject arbitrary HTML or JavaScript into the rendered document.
CVE-2026-109841 is a Subresource Integrity (SRI) verification bypass vulnerability in undici, the official HTTP/1.1 and HTTP/2 client library for Node.js that powers the global fetch() implementation. The flaw stems from improper handling of case sensitivity (CWE-178) when validating cryptographic hash algorithm tokens within SRI metadata. Because undici compared incoming algorithm identifiers against a strictly lowercase set without prior ASCII-lowercase normalization, valid uppercase or mixed-case tokens such as SHA256- or Sha384- were treated as unrecognized algorithms and discarded. Under SRI forward-compatibility rules, discarding all provided tokens results in an empty integrity list, causing undici to fail open and accept tampered HTTP response bodies without cryptographic verification.