@@ -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 ,
0 commit comments