Aug 4, 2026·6 min read·40 visits
GitPython versions <= 3.1.56 are vulnerable to arbitrary file reads and SSRF. By omitting target flags from internal argument validation tables, applications passing user kwargs to Repo.archive() or Repo.clone() can be exploited to retrieve system files or make outbound network requests.
An argument injection vulnerability in GitPython allows remote or local attackers with control over repository archive configuration options to retrieve arbitrary local files via native git archive commands. During clone operations, a sibling missing validation vulnerability in the clone option engine allows attackers to perform Server-Side Request Forgery via the git clone bundle-uri mechanism.
GitPython provides an object-oriented API wrapping native Git command-line interface utilities. Applications embedding GitPython often delegate operations such as file archiving and repository cloning to the underlying Git command engine. When invoking functions like Repo.archive() or Repo.clone(), the library dynamically translates Python keyword arguments into official command-line parameters passed directly to the local shell executing the Git CLI process.
To restrict execution vectors that allow command injection or unauthorized filesystem access, GitPython utilizes an internal validation layer. This layer matches incoming Python arguments against hardcoded denylists of known unsafe parameters. If a parameter matches the denylist, an exception is thrown, halting command execution.
During a code audit of version 3.1.56 and earlier, security researchers identified multiple missing parameters from these safety denylists. Specifically, the utility omitted --add-file and --add-virtual-file from the archive denylist, and --bundle-uri from the clone denylist. As a result, downstream applications that allow user-influenced parameters to reach GitPython components can be forced to read local files or perform unauthorized HTTP requests.
The root cause of this vulnerability lies in a membership incompleteness flaw within GitPython's verification lists located in git/repo/base.py. The validation scheme relies on checking arguments against a strict list of strings before formatting and passing them to the sub-process wrapper.
# Pre-patched unsafe_git_archive_options definition in git/repo/base.py
unsafe_git_archive_options = [
"--exec",
"--output",
"-o",
]The native git archive tool implements arguments designed to manipulate the final structure of the generated package without altering repository indices. The --add-file=<path> argument retrieves any accessible file from the underlying operating system and inserts it into the archived bundle. Similarly, --add-virtual-file=<path:content> constructs a dynamic file structure within the archive using supplied text content. Because both parameters were absent from the validation array, GitPython accepted them as safe options.
A similar architectural gap was documented in the clone wrapper logic. Standard Git protocol controls reject insecure transport mechanisms when configured to do so. However, native Git allows an alternate content acquisition source through the --bundle-uri=<uri> flag, which downloads pre-packaged repository files from a custom web address. The unsafe_git_clone_options array omitted this flag, enabling callers to circumvent protocol restrictions and force outbound network calls.
An analysis of the fix commit 7a4f5dcb7bf3cbcbf6e438017efcdfe0bc0d36ca reveals how the library maintainers patched the gap by expanding the validation vectors inside git/repo/base.py. The diff demonstrates the explicit mapping of the unsafe arguments to the existing denylist matrices.
diff --git a/git/repo/base.py b/git/repo/base.py
index ae99ed5f9..93d17252c 100644
--- a/git/repo/base.py
+++ b/git/repo/base.py
@@ -151,6 +151,8 @@ class Repo:
"-c",
# Can install hooks that execute during clone:
"--template",
+ # Fetches from a caller-controlled URL:
+ "--bundle-uri",
]
"""Options to :manpage:`git-clone(1)` that allow arbitrary commands to be executed.
@@ -172,6 +174,10 @@ class Repo:
# Writes output to a caller-controlled filesystem path.
"--output",
"-o",
+ # Reads from a caller-controlled filesystem path:
+ "--add-file",
+ # Injects a caller-controlled path and contents:
+ "--add-virtual-file",
]The update prevents validation bypasses. When Repo.archive() parses keyword parameters, any invocation mapping to add_file or add_virtual_file triggers a membership match, raising an UnsafeOptionError. The identical control mechanism handles bundle_uri mapping inside Repo.clone(). Testing files test_clone.py and test_repo.py were also modified to programmatically enforce that these specific CLI flags trigger immediate execution halts.
Exploitation relies on an application exposing the ability to run repository packaging or repository synchronization tasks where parameters are directly influenced by remote users.
In a target application configured to let users export repositories with dynamic formats, an attacker can specify the add_file argument pointing to local credentials or configurations. The internal system processes the command, binds the target path to the generated tar or zip archive, and writes the contents to the output stream. The output stream is then read by the attacker, leaking the requested local file.
In a cloning scenario, targeting the --bundle-uri parameter allows attackers to force the application server to make an HTTP request to an internal network location, such as the cloud metadata endpoint http://169.254.169.254/latest/meta-data/. This enables Server-Side Request Forgery and internal network scanning, bypassing network boundaries established to protect localized resources.
The potential consequences of this flaw depend on the access privileges of the host process running GitPython. Because --add-file bypasses standard repository constraints, it permits reading any file system item the current process owner has read access to. This includes sensitive system parameters, service accounts, database credentials, application source code, and user data.
The inclusion of --add-virtual-file creates high integrity risks. Attackers can inject rogue binary objects or source code modifications into exported release packages. Downstream consumers downloading these archives may execute untrusted payloads, converting a localized file read into a wider supply chain compromise.
The --bundle-uri bypass compromises network boundary confidentiality. Exploiting this parameter allows bad actors to probe internal ports, interface with private internal services, or exfiltrate cloud environment credentials from local management endpoints.
The primary resolution is upgrading the GitPython package to a secure release. Version 3.1.57 addresses both missing parameter lists and adds regression tests to ensure long-term stability.
If instant package updates are not feasible, code modifications must be implemented to replace denylisting logic with strict parameter allowlisting. Applications must not forward arbitrary, unvetted dictionary payloads directly to GitPython methods. Instead, translate incoming keys to an explicit list of allowed variables.
Network administrators should implement egress filtering rules to isolate build and archival systems from internal metadata services and private subnet ranges. Restricting outbound traffic prevents exploitation attempts leveraging the --bundle-uri SSRF vector.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
GitPython gitpython-developers | <= 3.1.56 | 3.1.57 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-73 |
| Attack Vector | Network |
| CVSS v3.1 | 6.5 |
| Exploit Status | Proof of Concept |
| Impact | Arbitrary File Read, Server-Side Request Forgery |
| Remediation Status | Official Patch Available |
The software allows user input to control or influence the paths or file names used in filesystem operations.
An authentication bypass vulnerability in pyLoad allows unauthenticated remote attackers to gain administrative API access. The vulnerability is caused by a logical flaw in the API key cache validation lookup, where authentication states are cached using only the public key identifier, skipping cryptographic token verification on cache hits.
An authorization bypass vulnerability in Strawberry GraphQL between versions 0.217.0 and 0.326.1 occurs when a synchronous permission handler returns an awaitable object (such as an unawaited coroutine). Due to Python's truthiness rules, the unawaited coroutine is evaluated as True, leading to an immediate bypass of security policies.
An uncontrolled resource consumption vulnerability in Strawberry GraphQL allows unauthenticated remote attackers to trigger a Denial of Service on persistent WebSocket connections using the legacy graphql-ws protocol. When the server enforces max_subscriptions_per_connection, naturally terminating subscriptions are not cleared from memory registries, leading to exhaustion of connection slots.
A high-severity type-confusion vulnerability exists in NearForm fast-jwt prior to version 6.3.0. The vulnerability allows attackers to bypass crucial claim validation steps (such as expiration, issuer, audience, and subject validations) by presenting a validly signed JSON Web Token structured as a JSON array instead of a JSON object. This occurs because the library's decoder fails to reject JSON arrays during type evaluation.
NearForm fast-jwt prior to version 6.3.0 is vulnerable to an input validation flaw where configuring verifier properties (such as clockTolerance, clockTimestamp, and cacheTTL) with non-finite values like Infinity or NaN allows attackers to bypass temporal claim validations, including expiration (exp) and activation (nbf) boundaries. This validation bypass can result in unauthorized session persistence and cache poisoning.
A critical cryptographic vulnerability in fast-jwt versions 6.2.x prior to 6.3.0 allows unauthenticated remote attackers to execute an asymmetric-to-symmetric algorithm confusion attack due to incomplete validation of leading non-whitespace prefixes.