@@ -131,6 +131,9 @@ class Repo:
131131git_dir :PathLike
132132"""The ``.git`` repository directory."""
133133
134+ safe :None
135+ """Whether this is operating using restricted protocol and execution access."""
136+
134137_common_dir :PathLike = ""
135138
136139# Precompiled regex
@@ -175,6 +178,7 @@ def __init__(
175178odbt :Type [LooseObjectDB ]= GitCmdObjectDB ,
176179search_parent_directories :bool = False ,
177180expand_vars :bool = True ,
181+ safe :bool = False ,
178182 )-> None :
179183R"""Create a new :class:`Repo` instance.
180184
@@ -204,6 +208,17 @@ def __init__(
204208 Please note that this was the default behaviour in older versions of
205209 GitPython, which is considered a bug though.
206210
211+ :param safe:
212+ Lock down the configuration to make it as safe as possible
213+ when working with publicly accessible, untrusted
214+ repositories. This disables all known options that can run
215+ an external program and limits networking to the HTTP
216+ protocol via https:// URLs. This might not cover Git config
217+ options that were added since this was implemented, or
218+ options that might have unknown exploit vectors. It is a
219+ best effort defense rather than an exhaustive protection
220+ measure.
221+
207222 :raise git.exc.InvalidGitRepositoryError:
208223
209224 :raise git.exc.NoSuchPathError:
@@ -235,6 +250,8 @@ def __init__(
235250if not os .path .exists (epath ):
236251raise NoSuchPathError (epath )
237252
253+ self .safe = safe
254+
238255# Walk up the path to find the `.git` dir.
239256curpath = epath
240257git_dir = None
@@ -309,7 +326,7 @@ def __init__(
309326# END working dir handling
310327
311328self .working_dir :PathLike = self ._working_tree_dir or self .common_dir
312- self .git = self .GitCommandWrapperType (self .working_dir )
329+ self .git = self .GitCommandWrapperType (self .working_dir , safe )
313330
314331# Special handling, in special times.
315332rootpath = osp .join (self .common_dir ,"objects" )
@@ -1305,6 +1322,7 @@ def init(
13051322mkdir :bool = True ,
13061323odbt :Type [GitCmdObjectDB ]= GitCmdObjectDB ,
13071324expand_vars :bool = True ,
1325+ safe :bool = False ,
13081326** kwargs :Any ,
13091327 )-> "Repo" :
13101328"""Initialize a git repository at the given path if specified.
@@ -1329,6 +1347,8 @@ def init(
13291347 information disclosure, allowing attackers to access the contents of
13301348 environment variables.
13311349
1350+ TODO :param safe:
1351+
13321352 :param kwargs:
13331353 Keyword arguments serving as additional options to the
13341354 :manpage:`git-init(1)` command.
@@ -1342,9 +1362,9 @@ def init(
13421362os .makedirs (path ,0o755 )
13431363
13441364# git command automatically chdir into the directory
1345- git = cls .GitCommandWrapperType (path )
1365+ git = cls .GitCommandWrapperType (path , safe )
13461366git .init (** kwargs )
1347- return cls (path ,odbt = odbt )
1367+ return cls (path ,odbt = odbt , safe = safe )
13481368
13491369@classmethod
13501370def _clone (
@@ -1357,6 +1377,7 @@ def _clone(
13571377multi_options :Optional [List [str ]]= None ,
13581378allow_unsafe_protocols :bool = False ,
13591379allow_unsafe_options :bool = False ,
1380+ safe :Union [bool ,None ]= None ,
13601381** kwargs :Any ,
13611382 )-> "Repo" :
13621383odbt = kwargs .pop ("odbt" ,odb_default_type )
@@ -1418,7 +1439,11 @@ def _clone(
14181439if not osp .isabs (path ):
14191440path = osp .join (git ._working_dir ,path )if git ._working_dir is not None else path
14201441
1421- repo = cls (path ,odbt = odbt )
1442+ # if safe is not explicitly defined, then the new Repo instance should inherit the safe value
1443+ if safe is None :
1444+ safe = git ._safe
1445+
1446+ repo = cls (path ,odbt = odbt ,safe = safe )
14221447
14231448# Retain env values that were passed to _clone().
14241449repo .git .update_environment (** git .environment ())
@@ -1501,6 +1526,7 @@ def clone_from(
15011526multi_options :Optional [List [str ]]= None ,
15021527allow_unsafe_protocols :bool = False ,
15031528allow_unsafe_options :bool = False ,
1529+ safe :bool = False ,
15041530** kwargs :Any ,
15051531 )-> "Repo" :
15061532"""Create a clone from the given URL.
@@ -1531,13 +1557,16 @@ def clone_from(
15311557 :param allow_unsafe_options:
15321558 Allow unsafe options to be used, like ``--upload-pack``.
15331559
1560+ :param safe:
1561+ TODO
1562+
15341563 :param kwargs:
15351564 See the :meth:`clone` method.
15361565
15371566 :return:
15381567 :class:`Repo` instance pointing to the cloned directory.
15391568 """
1540- git = cls .GitCommandWrapperType (os .getcwd ())
1569+ git = cls .GitCommandWrapperType (os .getcwd (), safe )
15411570if env is not None :
15421571git .update_environment (** env )
15431572return cls ._clone (
@@ -1549,6 +1578,7 @@ def clone_from(
15491578multi_options ,
15501579allow_unsafe_protocols = allow_unsafe_protocols ,
15511580allow_unsafe_options = allow_unsafe_options ,
1581+ safe = safe ,
15521582** kwargs ,
15531583 )
15541584