Skip to content

Commit 94e0fb0

Browse files
committed
Add a unit test for CVE-2023-40590
This adds test_it_executes_git_not_from_cwd to verify that the execute method does not use "git.exe" in the current directory on Windows, nor "git" in the current directory on Unix-like systems, when those files are executable. It adds a _chdir helper context manager to support this, because contextlib.chdir is only available on Python 3.11 and later.
1 parent 6029211 commit 94e0fb0

File tree

1 file changed

+31
-1
lines changed

1 file changed

+31
-1
lines changed

test/test_git.py

+31-1
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
#
55
# This module is part of GitPython and is released under
66
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
7+
import contextlib
78
import os
9+
import shutil
810
import subprocess
911
import sys
10-
from tempfile import TemporaryFile
12+
from tempfile import TemporaryDirectory, TemporaryFile
1113
from unittest import mock
1214

1315
from git import Git, refresh, GitCommandError, GitCommandNotFound, Repo, cmd
@@ -20,6 +22,17 @@
2022
from git.compat import is_win
2123

2224

25+
@contextlib.contextmanager
26+
def _chdir(new_dir):
27+
"""Context manager to temporarily change directory. Not reentrant."""
28+
old_dir = os.getcwd()
29+
os.chdir(new_dir)
30+
try:
31+
yield
32+
finally:
33+
os.chdir(old_dir)
34+
35+
2336
class TestGit(TestBase):
2437
@classmethod
2538
def setUpClass(cls):
@@ -75,6 +88,23 @@ def test_it_transforms_kwargs_into_git_command_arguments(self):
7588
def test_it_executes_git_to_shell_and_returns_result(self):
7689
self.assertRegex(self.git.execute(["git", "version"]), r"^git version [\d\.]{2}.*$")
7790

91+
def test_it_executes_git_not_from_cwd(self):
92+
with TemporaryDirectory() as tmpdir:
93+
if is_win:
94+
# Copy an actual binary executable that is not git.
95+
other_exe_path = os.path.join(os.getenv("WINDIR"), "system32", "hostname.exe")
96+
impostor_path = os.path.join(tmpdir, "git.exe")
97+
shutil.copy(other_exe_path, impostor_path)
98+
else:
99+
# Create a shell script that doesn't do anything.
100+
impostor_path = os.path.join(tmpdir, "git")
101+
with open(impostor_path, mode="w", encoding="utf-8") as file:
102+
print("#!/bin/sh", file=file)
103+
os.chmod(impostor_path, 0o755)
104+
105+
with _chdir(tmpdir):
106+
self.assertRegex(self.git.execute(["git", "version"]), r"^git version [\d\.]{2}.*$")
107+
78108
def test_it_accepts_stdin(self):
79109
filename = fixture_path("cat_file_blob")
80110
with open(filename, "r") as fh:

0 commit comments

Comments
 (0)