diff options
| author | Steve Kowalik <steven@wedontsleep.org> | 2022-12-20 17:05:50 +1100 |
|---|---|---|
| committer | Santos Gallegos <stsewd@proton.me> | 2022-12-23 16:16:21 -0500 |
| commit | 2625ed9fc074091c531c27ffcba7902771130261 (patch) | |
| tree | 0f3589b06f2b63851addf126b245073cad7eacbf /test | |
| parent | 787359d80d80225095567340aa5e7ec01847fa9a (diff) | |
| download | gitpython-2625ed9fc074091c531c27ffcba7902771130261.tar.gz | |
Forbid unsafe protocol URLs in Repo.clone{,_from}()
Since the URL is passed directly to git clone, and the remote-ext helper
will happily execute shell commands, so by default disallow URLs that
contain a "::" unless a new unsafe_protocols kwarg is passed.
(CVE-2022-24439)
Fixes #1515
Diffstat (limited to 'test')
| -rw-r--r-- | test/test_repo.py | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/test/test_repo.py b/test/test_repo.py index 6382db7e..53cae3cd 100644 --- a/test/test_repo.py +++ b/test/test_repo.py @@ -13,6 +13,7 @@ import pathlib import pickle import sys import tempfile +import uuid from unittest import mock, skipIf, SkipTest import pytest @@ -37,6 +38,7 @@ from git import ( ) from git.exc import ( BadObject, + UnsafeOptionsUsedError, ) from git.repo.fun import touch from test.lib import TestBase, with_rw_repo, fixture @@ -263,6 +265,40 @@ class TestRepo(TestBase): to_path=rw_dir, ) + def test_unsafe_options(self): + self.assertFalse(Repo.unsafe_options("github.com/deploy/deploy")) + + def test_unsafe_options_ext_url(self): + self.assertTrue(Repo.unsafe_options("ext::ssh")) + + def test_unsafe_options_multi_options_upload_pack(self): + self.assertTrue(Repo.unsafe_options("", ["--upload-pack='touch foo'"])) + + def test_unsafe_options_multi_options_config_user(self): + self.assertFalse(Repo.unsafe_options("", ["--config user"])) + + def test_unsafe_options_multi_options_config_protocol(self): + self.assertTrue(Repo.unsafe_options("", ["--config protocol.foo"])) + + def test_clone_from_forbids_helper_urls_by_default(self): + with self.assertRaises(UnsafeOptionsUsedError): + Repo.clone_from("ext::sh -c touch% /tmp/foo", "tmp") + + @with_rw_repo("HEAD") + def test_clone_from_allow_unsafe(self, repo): + bad_filename = pathlib.Path(f'{tempfile.gettempdir()}/{uuid.uuid4()}') + bad_url = f'ext::sh -c touch% {bad_filename}' + try: + repo.clone_from( + bad_url, 'tmp', + multi_options=["-c protocol.ext.allow=always"], + unsafe_protocols=True + ) + except GitCommandError: + pass + self.assertTrue(bad_filename.is_file()) + bad_filename.unlink() + @with_rw_repo("HEAD") def test_max_chunk_size(self, repo): class TestOutputStream(TestBase): |
