@@ -539,6 +539,23 @@ class Remote(LazyMixin, IterableObj):
539
539
__slots__ = ("repo" ,"name" ,"_config_reader" )
540
540
_id_attribute_ = "name"
541
541
542
+ unsafe_git_fetch_options = [
543
+ # This option allows users to execute arbitrary commands.
544
+ # https://git-scm.com/docs/git-fetch#Documentation/git-fetch.txt---upload-packltupload-packgt
545
+ "--upload-pack" ,
546
+ ]
547
+ unsafe_git_pull_options = [
548
+ # This option allows users to execute arbitrary commands.
549
+ # https://git-scm.com/docs/git-pull#Documentation/git-pull.txt---upload-packltupload-packgt
550
+ "--upload-pack"
551
+ ]
552
+ unsafe_git_push_options = [
553
+ # This option allows users to execute arbitrary commands.
554
+ # https://git-scm.com/docs/git-push#Documentation/git-push.txt---execltgit-receive-packgt
555
+ "--receive-pack" ,
556
+ "--exec" ,
557
+ ]
558
+
542
559
def __init__ (self ,repo :"Repo" ,name :str )-> None :
543
560
"""Initialize a remote instance
544
561
@@ -615,7 +632,9 @@ def iter_items(cls, repo: "Repo", *args: Any, **kwargs: Any) -> Iterator["Remote
615
632
yield Remote (repo ,section [lbound + 1 :rbound ])
616
633
# END for each configuration section
617
634
618
- def set_url (self ,new_url :str ,old_url :Optional [str ]= None ,** kwargs :Any )-> "Remote" :
635
+ def set_url (
636
+ self ,new_url :str ,old_url :Optional [str ]= None ,allow_unsafe_protocols :bool = False ,** kwargs :Any
637
+ )-> "Remote" :
619
638
"""Configure URLs on current remote (cf command git remote set_url)
620
639
621
640
This command manages URLs on the remote.
@@ -624,15 +643,17 @@ def set_url(self, new_url: str, old_url: Optional[str] = None, **kwargs: Any) ->
624
643
:param old_url: when set, replaces this URL with new_url for the remote
625
644
:return: self
626
645
"""
646
+ if not allow_unsafe_protocols :
647
+ Git .check_unsafe_protocols (new_url )
627
648
scmd = "set-url"
628
649
kwargs ["insert_kwargs_after" ]= scmd
629
650
if old_url :
630
- self .repo .git .remote (scmd ,self .name ,new_url ,old_url ,** kwargs )
651
+ self .repo .git .remote (scmd ,"--" , self .name ,new_url ,old_url ,** kwargs )
631
652
else :
632
- self .repo .git .remote (scmd ,self .name ,new_url ,** kwargs )
653
+ self .repo .git .remote (scmd ,"--" , self .name ,new_url ,** kwargs )
633
654
return self
634
655
635
- def add_url (self ,url :str ,** kwargs :Any )-> "Remote" :
656
+ def add_url (self ,url :str ,allow_unsafe_protocols : bool = False , ** kwargs :Any )-> "Remote" :
636
657
"""Adds a new url on current remote (special case of git remote set_url)
637
658
638
659
This command adds new URLs to a given remote, making it possible to have
@@ -641,7 +662,7 @@ def add_url(self, url: str, **kwargs: Any) -> "Remote":
641
662
:param url: string being the URL to add as an extra remote URL
642
663
:return: self
643
664
"""
644
- return self .set_url (url ,add = True )
665
+ return self .set_url (url ,add = True , allow_unsafe_protocols = allow_unsafe_protocols )
645
666
646
667
def delete_url (self ,url :str ,** kwargs :Any )-> "Remote" :
647
668
"""Deletes a new url on current remote (special case of git remote set_url)
@@ -733,7 +754,7 @@ def stale_refs(self) -> IterableList[Reference]:
733
754
return out_refs
734
755
735
756
@classmethod
736
- def create (cls ,repo :"Repo" ,name :str ,url :str ,** kwargs :Any )-> "Remote" :
757
+ def create (cls ,repo :"Repo" ,name :str ,url :str ,allow_unsafe_protocols : bool = False , ** kwargs :Any )-> "Remote" :
737
758
"""Create a new remote to the given repository
738
759
:param repo: Repository instance that is to receive the new remote
739
760
:param name: Desired name of the remote
@@ -743,7 +764,10 @@ def create(cls, repo: "Repo", name: str, url: str, **kwargs: Any) -> "Remote":
743
764
:raise GitCommandError: in case an origin with that name already exists"""
744
765
scmd = "add"
745
766
kwargs ["insert_kwargs_after" ]= scmd
746
- repo .git .remote (scmd ,name ,Git .polish_url (url ),** kwargs )
767
+ url = Git .polish_url (url )
768
+ if not allow_unsafe_protocols :
769
+ Git .check_unsafe_protocols (url )
770
+ repo .git .remote (scmd ,"--" ,name ,url ,** kwargs )
747
771
return cls (repo ,name )
748
772
749
773
# add is an alias
@@ -925,6 +949,8 @@ def fetch(
925
949
progress :Union [RemoteProgress ,None ,"UpdateProgress" ]= None ,
926
950
verbose :bool = True ,
927
951
kill_after_timeout :Union [None ,float ]= None ,
952
+ allow_unsafe_protocols :bool = False ,
953
+ allow_unsafe_options :bool = False ,
928
954
** kwargs :Any ,
929
955
)-> IterableList [FetchInfo ]:
930
956
"""Fetch the latest changes for this remote
@@ -967,6 +993,14 @@ def fetch(
967
993
else :
968
994
args = [refspec ]
969
995
996
+ if not allow_unsafe_protocols :
997
+ for ref in args :
998
+ if ref :
999
+ Git .check_unsafe_protocols (ref )
1000
+
1001
+ if not allow_unsafe_options :
1002
+ Git .check_unsafe_options (options = list (kwargs .keys ()),unsafe_options = self .unsafe_git_fetch_options )
1003
+
970
1004
proc = self .repo .git .fetch (
971
1005
"--" ,self ,* args ,as_process = True ,with_stdout = False ,universal_newlines = True ,v = verbose ,** kwargs
972
1006
)
@@ -980,6 +1014,8 @@ def pull(
980
1014
refspec :Union [str ,List [str ],None ]= None ,
981
1015
progress :Union [RemoteProgress ,"UpdateProgress" ,None ]= None ,
982
1016
kill_after_timeout :Union [None ,float ]= None ,
1017
+ allow_unsafe_protocols :bool = False ,
1018
+ allow_unsafe_options :bool = False ,
983
1019
** kwargs :Any ,
984
1020
)-> IterableList [FetchInfo ]:
985
1021
"""Pull changes from the given branch, being the same as a fetch followed
@@ -994,6 +1030,15 @@ def pull(
994
1030
# No argument refspec, then ensure the repo's config has a fetch refspec.
995
1031
self ._assert_refspec ()
996
1032
kwargs = add_progress (kwargs ,self .repo .git ,progress )
1033
+
1034
+ refspec = Git ._unpack_args (refspec or [])
1035
+ if not allow_unsafe_protocols :
1036
+ for ref in refspec :
1037
+ Git .check_unsafe_protocols (ref )
1038
+
1039
+ if not allow_unsafe_options :
1040
+ Git .check_unsafe_options (options = list (kwargs .keys ()),unsafe_options = self .unsafe_git_pull_options )
1041
+
997
1042
proc = self .repo .git .pull (
998
1043
"--" ,self ,refspec ,with_stdout = False ,as_process = True ,universal_newlines = True ,v = True ,** kwargs
999
1044
)
@@ -1007,6 +1052,8 @@ def push(
1007
1052
refspec :Union [str ,List [str ],None ]= None ,
1008
1053
progress :Union [RemoteProgress ,"UpdateProgress" ,Callable [...,RemoteProgress ],None ]= None ,
1009
1054
kill_after_timeout :Union [None ,float ]= None ,
1055
+ allow_unsafe_protocols :bool = False ,
1056
+ allow_unsafe_options :bool = False ,
1010
1057
** kwargs :Any ,
1011
1058
)-> PushInfoList :
1012
1059
"""Push changes from source branch in refspec to target branch in refspec.
@@ -1037,6 +1084,15 @@ def push(
1037
1084
be 0.
1038
1085
Call ``.raise_if_error()`` on the returned object to raise on any failure."""
1039
1086
kwargs = add_progress (kwargs ,self .repo .git ,progress )
1087
+
1088
+ refspec = Git ._unpack_args (refspec or [])
1089
+ if not allow_unsafe_protocols :
1090
+ for ref in refspec :
1091
+ Git .check_unsafe_protocols (ref )
1092
+
1093
+ if not allow_unsafe_options :
1094
+ Git .check_unsafe_options (options = list (kwargs .keys ()),unsafe_options = self .unsafe_git_push_options )
1095
+
1040
1096
proc = self .repo .git .push (
1041
1097
"--" ,
1042
1098
self ,