@@ -131,6 +131,9 @@ class Repo:
131131 git_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__(
175178 odbt : Type [LooseObjectDB ] = GitCmdObjectDB ,
176179 search_parent_directories : bool = False ,
177180 expand_vars : bool = True ,
181+ safe : bool = False ,
178182 ) -> None :
179183 R"""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__(
235250 if not os .path .exists (epath ):
236251 raise NoSuchPathError (epath )
237252
253+ self .safe = safe
254+
238255 # Walk up the path to find the `.git` dir.
239256 curpath = epath
240257 git_dir = None
@@ -309,7 +326,7 @@ def __init__(
309326 # END working dir handling
310327
311328 self .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.
315332 rootpath = osp .join (self .common_dir , "objects" )
@@ -1305,6 +1322,7 @@ def init(
13051322 mkdir : bool = True ,
13061323 odbt : Type [GitCmdObjectDB ] = GitCmdObjectDB ,
13071324 expand_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(
13421362 os .makedirs (path , 0o755 )
13431363
13441364 # git command automatically chdir into the directory
1345- git = cls .GitCommandWrapperType (path )
1365+ git = cls .GitCommandWrapperType (path , safe )
13461366 git .init (** kwargs )
1347- return cls (path , odbt = odbt )
1367+ return cls (path , odbt = odbt , safe = safe )
13481368
13491369 @classmethod
13501370 def _clone (
@@ -1357,6 +1377,7 @@ def _clone(
13571377 multi_options : Optional [List [str ]] = None ,
13581378 allow_unsafe_protocols : bool = False ,
13591379 allow_unsafe_options : bool = False ,
1380+ safe : Union [bool , None ] = None ,
13601381 ** kwargs : Any ,
13611382 ) -> "Repo" :
13621383 odbt = kwargs .pop ("odbt" , odb_default_type )
@@ -1418,7 +1439,11 @@ def _clone(
14181439 if not osp .isabs (path ):
14191440 path = 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().
14241449 repo .git .update_environment (** git .environment ())
@@ -1501,6 +1526,7 @@ def clone_from(
15011526 multi_options : Optional [List [str ]] = None ,
15021527 allow_unsafe_protocols : bool = False ,
15031528 allow_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 )
15411570 if env is not None :
15421571 git .update_environment (** env )
15431572 return cls ._clone (
@@ -1549,6 +1578,7 @@ def clone_from(
15491578 multi_options ,
15501579 allow_unsafe_protocols = allow_unsafe_protocols ,
15511580 allow_unsafe_options = allow_unsafe_options ,
1581+ safe = safe ,
15521582 ** kwargs ,
15531583 )
15541584
0 commit comments