From 5c59e0d63da6180db8a0b349f0ad36fef42aceed Mon Sep 17 00:00:00 2001
From: Sylvain Beucler <beuc@beuc.net>
Date: Mon, 10 Jul 2023 16:10:10 +0200
Subject: [PATCH] Block insecure non-multi options in clone/clone_from
 Follow-up to #1521

---
 git/repo/base.py  |  2 ++
 test/test_repo.py | 24 +++++++++++++++++++++++-
 2 files changed, 25 insertions(+), 1 deletion(-)

--- python-git-3.1.30.orig/git/repo/base.py
+++ python-git-3.1.30/git/repo/base.py
@@ -1188,6 +1188,8 @@ class Repo(object):
 
         if not allow_unsafe_protocols:
             Git.check_unsafe_protocols(str(url))
+        if not allow_unsafe_options:
+            Git.check_unsafe_options(options=list(kwargs.keys()), unsafe_options=cls.unsafe_git_clone_options)
         if not allow_unsafe_options and multi_options:
             Git.check_unsafe_options(options=multi_options, unsafe_options=cls.unsafe_git_clone_options)
 
--- python-git-3.1.30.orig/test/test_repo.py
+++ python-git-3.1.30/test/test_repo.py
@@ -281,6 +281,17 @@ class TestRepo(TestBase):
                 rw_repo.clone(tmp_dir, multi_options=[unsafe_option])
             assert not tmp_file.exists()
 
+        unsafe_options = [
+            {"upload-pack": f"touch {tmp_file}"},
+            {"u": f"touch {tmp_file}"},
+            {"config": "protocol.ext.allow=always"},
+            {"c": "protocol.ext.allow=always"},
+        ]
+        for unsafe_option in unsafe_options:
+            with self.assertRaises(UnsafeOptionError):
+                rw_repo.clone(tmp_dir, **unsafe_option)
+            assert not tmp_file.exists()
+
     @with_rw_repo("HEAD")
     def test_clone_unsafe_options_allowed(self, rw_repo):
         tmp_dir = pathlib.Path(tempfile.mkdtemp())
@@ -337,6 +348,17 @@ class TestRepo(TestBase):
                 Repo.clone_from(rw_repo.working_dir, tmp_dir, multi_options=[unsafe_option])
             assert not tmp_file.exists()
 
+        unsafe_options = [
+            {"upload-pack": f"touch {tmp_file}"},
+            {"u": f"touch {tmp_file}"},
+            {"config": "protocol.ext.allow=always"},
+            {"c": "protocol.ext.allow=always"},
+        ]
+        for unsafe_option in unsafe_options:
+            with self.assertRaises(UnsafeOptionError):
+                Repo.clone_from(rw_repo.working_dir, tmp_dir, **unsafe_option)
+            assert not tmp_file.exists()
+
     @with_rw_repo("HEAD")
     def test_clone_from_unsafe_options_allowed(self, rw_repo):
         tmp_dir = pathlib.Path(tempfile.mkdtemp())
