@@ -535,6 +535,23 @@ class Remote(LazyMixin, IterableObj):
535
535
__slots__ = ("repo" , "name" , "_config_reader" )
536
536
_id_attribute_ = "name"
537
537
538
+ unsafe_git_fetch_options = [
539
+ # This option allows users to execute arbitrary commands.
540
+ # https://git-scm.com/docs/git-fetch#Documentation/git-fetch.txt---upload-packltupload-packgt
541
+ "--upload-pack" ,
542
+ ]
543
+ unsafe_git_pull_options = [
544
+ # This option allows users to execute arbitrary commands.
545
+ # https://git-scm.com/docs/git-pull#Documentation/git-pull.txt---upload-packltupload-packgt
546
+ "--upload-pack"
547
+ ]
548
+ unsafe_git_push_options = [
549
+ # This option allows users to execute arbitrary commands.
550
+ # https://git-scm.com/docs/git-push#Documentation/git-push.txt---execltgit-receive-packgt
551
+ "--receive-pack" ,
552
+ "--exec" ,
553
+ ]
554
+
538
555
def __init__ (self , repo : "Repo" , name : str ) -> None :
539
556
"""Initialize a remote instance
540
557
@@ -611,7 +628,9 @@ def iter_items(cls, repo: "Repo", *args: Any, **kwargs: Any) -> Iterator["Remote
611
628
yield Remote (repo , section [lbound + 1 : rbound ])
612
629
# END for each configuration section
613
630
614
- def set_url (self , new_url : str , old_url : Optional [str ] = None , ** kwargs : Any ) -> "Remote" :
631
+ def set_url (
632
+ self , new_url : str , old_url : Optional [str ] = None , allow_unsafe_protocols : bool = False , ** kwargs : Any
633
+ ) -> "Remote" :
615
634
"""Configure URLs on current remote (cf command git remote set_url)
616
635
617
636
This command manages URLs on the remote.
@@ -620,15 +639,17 @@ def set_url(self, new_url: str, old_url: Optional[str] = None, **kwargs: Any) ->
620
639
:param old_url: when set, replaces this URL with new_url for the remote
621
640
:return: self
622
641
"""
642
+ if not allow_unsafe_protocols :
643
+ Git .check_unsafe_protocols (new_url )
623
644
scmd = "set-url"
624
645
kwargs ["insert_kwargs_after" ] = scmd
625
646
if old_url :
626
- self .repo .git .remote (scmd , self .name , new_url , old_url , ** kwargs )
647
+ self .repo .git .remote (scmd , "--" , self .name , new_url , old_url , ** kwargs )
627
648
else :
628
- self .repo .git .remote (scmd , self .name , new_url , ** kwargs )
649
+ self .repo .git .remote (scmd , "--" , self .name , new_url , ** kwargs )
629
650
return self
630
651
631
- def add_url (self , url : str , ** kwargs : Any ) -> "Remote" :
652
+ def add_url (self , url : str , allow_unsafe_protocols : bool = False , ** kwargs : Any ) -> "Remote" :
632
653
"""Adds a new url on current remote (special case of git remote set_url)
633
654
634
655
This command adds new URLs to a given remote, making it possible to have
@@ -637,6 +658,8 @@ def add_url(self, url: str, **kwargs: Any) -> "Remote":
637
658
:param url: string being the URL to add as an extra remote URL
638
659
:return: self
639
660
"""
661
+ if not allow_unsafe_protocols :
662
+ Git .check_unsafe_protocols (url )
640
663
return self .set_url (url , add = True )
641
664
642
665
def delete_url (self , url : str , ** kwargs : Any ) -> "Remote" :
@@ -729,7 +752,7 @@ def stale_refs(self) -> IterableList[Reference]:
729
752
return out_refs
730
753
731
754
@classmethod
732
- def create (cls , repo : "Repo" , name : str , url : str , ** kwargs : Any ) -> "Remote" :
755
+ def create (cls , repo : "Repo" , name : str , url : str , allow_unsafe_protocols : bool = False , ** kwargs : Any ) -> "Remote" :
733
756
"""Create a new remote to the given repository
734
757
:param repo: Repository instance that is to receive the new remote
735
758
:param name: Desired name of the remote
@@ -739,7 +762,10 @@ def create(cls, repo: "Repo", name: str, url: str, **kwargs: Any) -> "Remote":
739
762
:raise GitCommandError: in case an origin with that name already exists"""
740
763
scmd = "add"
741
764
kwargs ["insert_kwargs_after" ] = scmd
742
- repo .git .remote (scmd , name , Git .polish_url (url ), ** kwargs )
765
+ url = Git .polish_url (url )
766
+ if not allow_unsafe_protocols :
767
+ Git .check_unsafe_protocols (url )
768
+ repo .git .remote (scmd , "--" , name , url , ** kwargs )
743
769
return cls (repo , name )
744
770
745
771
# add is an alias
@@ -921,6 +947,8 @@ def fetch(
921
947
progress : Union [RemoteProgress , None , "UpdateProgress" ] = None ,
922
948
verbose : bool = True ,
923
949
kill_after_timeout : Union [None , float ] = None ,
950
+ allow_unsafe_protocols : bool = False ,
951
+ allow_unsafe_options : bool = False ,
924
952
** kwargs : Any ,
925
953
) -> IterableList [FetchInfo ]:
926
954
"""Fetch the latest changes for this remote
@@ -963,6 +991,14 @@ def fetch(
963
991
else :
964
992
args = [refspec ]
965
993
994
+ if not allow_unsafe_protocols :
995
+ for ref in args :
996
+ if ref :
997
+ Git .check_unsafe_protocols (ref )
998
+
999
+ if not allow_unsafe_options :
1000
+ Git .check_unsafe_options (options = list (kwargs .keys ()), unsafe_options = self .unsafe_git_fetch_options )
1001
+
966
1002
proc = self .repo .git .fetch (
967
1003
"--" , self , * args , as_process = True , with_stdout = False , universal_newlines = True , v = verbose , ** kwargs
968
1004
)
@@ -976,6 +1012,8 @@ def pull(
976
1012
refspec : Union [str , List [str ], None ] = None ,
977
1013
progress : Union [RemoteProgress , "UpdateProgress" , None ] = None ,
978
1014
kill_after_timeout : Union [None , float ] = None ,
1015
+ allow_unsafe_protocols : bool = False ,
1016
+ allow_unsafe_options : bool = False ,
979
1017
** kwargs : Any ,
980
1018
) -> IterableList [FetchInfo ]:
981
1019
"""Pull changes from the given branch, being the same as a fetch followed
@@ -990,6 +1028,16 @@ def pull(
990
1028
# No argument refspec, then ensure the repo's config has a fetch refspec.
991
1029
self ._assert_refspec ()
992
1030
kwargs = add_progress (kwargs , self .repo .git , progress )
1031
+
1032
+ if not allow_unsafe_protocols and refspec :
1033
+ if isinstance (refspec , str ):
1034
+ Git .check_unsafe_protocols (refspec )
1035
+ else :
1036
+ for ref in refspec :
1037
+ Git .check_unsafe_protocols (ref )
1038
+ if not allow_unsafe_options :
1039
+ Git .check_unsafe_options (options = list (kwargs .keys ()), unsafe_options = self .unsafe_git_pull_options )
1040
+
993
1041
proc = self .repo .git .pull (
994
1042
"--" , self , refspec , with_stdout = False , as_process = True , universal_newlines = True , v = True , ** kwargs
995
1043
)
@@ -1003,6 +1051,8 @@ def push(
1003
1051
refspec : Union [str , List [str ], None ] = None ,
1004
1052
progress : Union [RemoteProgress , "UpdateProgress" , Callable [..., RemoteProgress ], None ] = None ,
1005
1053
kill_after_timeout : Union [None , float ] = None ,
1054
+ allow_unsafe_protocols : bool = False ,
1055
+ allow_unsafe_options : bool = False ,
1006
1056
** kwargs : Any ,
1007
1057
) -> IterableList [PushInfo ]:
1008
1058
"""Push changes from source branch in refspec to target branch in refspec.
@@ -1033,6 +1083,17 @@ def push(
1033
1083
If the operation fails completely, the length of the returned IterableList will
1034
1084
be 0."""
1035
1085
kwargs = add_progress (kwargs , self .repo .git , progress )
1086
+
1087
+ if not allow_unsafe_protocols and refspec :
1088
+ if isinstance (refspec , str ):
1089
+ Git .check_unsafe_protocols (refspec )
1090
+ else :
1091
+ for ref in refspec :
1092
+ Git .check_unsafe_protocols (ref )
1093
+
1094
+ if not allow_unsafe_options :
1095
+ Git .check_unsafe_options (options = list (kwargs .keys ()), unsafe_options = self .unsafe_git_push_options )
1096
+
1036
1097
proc = self .repo .git .push (
1037
1098
"--" ,
1038
1099
self ,
0 commit comments