@@ -131,6 +131,9 @@ class Repo:
131
131
git_dir :PathLike
132
132
"""The ``.git`` repository directory."""
133
133
134
+ safe :None
135
+ """Whether this is operating using restricted protocol and execution access."""
136
+
134
137
_common_dir :PathLike = ""
135
138
136
139
# Precompiled regex
@@ -175,6 +178,7 @@ def __init__(
175
178
odbt :Type [LooseObjectDB ]= GitCmdObjectDB ,
176
179
search_parent_directories :bool = False ,
177
180
expand_vars :bool = True ,
181
+ safe :bool = False ,
178
182
)-> None :
179
183
R"""Create a new :class:`Repo` instance.
180
184
@@ -204,6 +208,17 @@ def __init__(
204
208
Please note that this was the default behaviour in older versions of
205
209
GitPython, which is considered a bug though.
206
210
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
+
207
222
:raise git.exc.InvalidGitRepositoryError:
208
223
209
224
:raise git.exc.NoSuchPathError:
@@ -235,6 +250,8 @@ def __init__(
235
250
if not os .path .exists (epath ):
236
251
raise NoSuchPathError (epath )
237
252
253
+ self .safe = safe
254
+
238
255
# Walk up the path to find the `.git` dir.
239
256
curpath = epath
240
257
git_dir = None
@@ -309,7 +326,7 @@ def __init__(
309
326
# END working dir handling
310
327
311
328
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 )
313
330
314
331
# Special handling, in special times.
315
332
rootpath = osp .join (self .common_dir ,"objects" )
@@ -1305,6 +1322,7 @@ def init(
1305
1322
mkdir :bool = True ,
1306
1323
odbt :Type [GitCmdObjectDB ]= GitCmdObjectDB ,
1307
1324
expand_vars :bool = True ,
1325
+ safe :bool = False ,
1308
1326
** kwargs :Any ,
1309
1327
)-> "Repo" :
1310
1328
"""Initialize a git repository at the given path if specified.
@@ -1329,6 +1347,8 @@ def init(
1329
1347
information disclosure, allowing attackers to access the contents of
1330
1348
environment variables.
1331
1349
1350
+ TODO :param safe:
1351
+
1332
1352
:param kwargs:
1333
1353
Keyword arguments serving as additional options to the
1334
1354
:manpage:`git-init(1)` command.
@@ -1342,9 +1362,9 @@ def init(
1342
1362
os .makedirs (path ,0o755 )
1343
1363
1344
1364
# git command automatically chdir into the directory
1345
- git = cls .GitCommandWrapperType (path )
1365
+ git = cls .GitCommandWrapperType (path , safe )
1346
1366
git .init (** kwargs )
1347
- return cls (path ,odbt = odbt )
1367
+ return cls (path ,odbt = odbt , safe = safe )
1348
1368
1349
1369
@classmethod
1350
1370
def _clone (
@@ -1357,6 +1377,7 @@ def _clone(
1357
1377
multi_options :Optional [List [str ]]= None ,
1358
1378
allow_unsafe_protocols :bool = False ,
1359
1379
allow_unsafe_options :bool = False ,
1380
+ safe :Union [bool ,None ]= None ,
1360
1381
** kwargs :Any ,
1361
1382
)-> "Repo" :
1362
1383
odbt = kwargs .pop ("odbt" ,odb_default_type )
@@ -1418,7 +1439,11 @@ def _clone(
1418
1439
if not osp .isabs (path ):
1419
1440
path = osp .join (git ._working_dir ,path )if git ._working_dir is not None else path
1420
1441
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 )
1422
1447
1423
1448
# Retain env values that were passed to _clone().
1424
1449
repo .git .update_environment (** git .environment ())
@@ -1501,6 +1526,7 @@ def clone_from(
1501
1526
multi_options :Optional [List [str ]]= None ,
1502
1527
allow_unsafe_protocols :bool = False ,
1503
1528
allow_unsafe_options :bool = False ,
1529
+ safe :bool = False ,
1504
1530
** kwargs :Any ,
1505
1531
)-> "Repo" :
1506
1532
"""Create a clone from the given URL.
@@ -1531,13 +1557,16 @@ def clone_from(
1531
1557
:param allow_unsafe_options:
1532
1558
Allow unsafe options to be used, like ``--upload-pack``.
1533
1559
1560
+ :param safe:
1561
+ TODO
1562
+
1534
1563
:param kwargs:
1535
1564
See the :meth:`clone` method.
1536
1565
1537
1566
:return:
1538
1567
:class:`Repo` instance pointing to the cloned directory.
1539
1568
"""
1540
- git = cls .GitCommandWrapperType (os .getcwd ())
1569
+ git = cls .GitCommandWrapperType (os .getcwd (), safe )
1541
1570
if env is not None :
1542
1571
git .update_environment (** env )
1543
1572
return cls ._clone (
@@ -1549,6 +1578,7 @@ def clone_from(
1549
1578
multi_options ,
1550
1579
allow_unsafe_protocols = allow_unsafe_protocols ,
1551
1580
allow_unsafe_options = allow_unsafe_options ,
1581
+ safe = safe ,
1552
1582
** kwargs ,
1553
1583
)
1554
1584