@@ -539,6 +539,23 @@ class Remote(LazyMixin, IterableObj):
539539__slots__ = ("repo" ,"name" ,"_config_reader" )
540540_id_attribute_ = "name"
541541
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+
542559def __init__ (self ,repo :"Repo" ,name :str )-> None :
543560"""Initialize a remote instance
544561
@@ -615,7 +632,9 @@ def iter_items(cls, repo: "Repo", *args: Any, **kwargs: Any) -> Iterator["Remote
615632yield Remote (repo ,section [lbound + 1 :rbound ])
616633# END for each configuration section
617634
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" :
619638"""Configure URLs on current remote (cf command git remote set_url)
620639
621640 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) ->
624643 :param old_url: when set, replaces this URL with new_url for the remote
625644 :return: self
626645 """
646+ if not allow_unsafe_protocols :
647+ Git .check_unsafe_protocols (new_url )
627648scmd = "set-url"
628649kwargs ["insert_kwargs_after" ]= scmd
629650if 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 )
631652else :
632- self .repo .git .remote (scmd ,self .name ,new_url ,** kwargs )
653+ self .repo .git .remote (scmd ,"--" , self .name ,new_url ,** kwargs )
633654return self
634655
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" :
636657"""Adds a new url on current remote (special case of git remote set_url)
637658
638659 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":
641662 :param url: string being the URL to add as an extra remote URL
642663 :return: self
643664 """
644- return self .set_url (url ,add = True )
665+ return self .set_url (url ,add = True , allow_unsafe_protocols = allow_unsafe_protocols )
645666
646667def delete_url (self ,url :str ,** kwargs :Any )-> "Remote" :
647668"""Deletes a new url on current remote (special case of git remote set_url)
@@ -733,7 +754,7 @@ def stale_refs(self) -> IterableList[Reference]:
733754return out_refs
734755
735756@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" :
737758"""Create a new remote to the given repository
738759 :param repo: Repository instance that is to receive the new remote
739760 :param name: Desired name of the remote
@@ -743,7 +764,10 @@ def create(cls, repo: "Repo", name: str, url: str, **kwargs: Any) -> "Remote":
743764 :raise GitCommandError: in case an origin with that name already exists"""
744765scmd = "add"
745766kwargs ["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 )
747771return cls (repo ,name )
748772
749773# add is an alias
@@ -925,6 +949,8 @@ def fetch(
925949progress :Union [RemoteProgress ,None ,"UpdateProgress" ]= None ,
926950verbose :bool = True ,
927951kill_after_timeout :Union [None ,float ]= None ,
952+ allow_unsafe_protocols :bool = False ,
953+ allow_unsafe_options :bool = False ,
928954** kwargs :Any ,
929955 )-> IterableList [FetchInfo ]:
930956"""Fetch the latest changes for this remote
@@ -967,6 +993,14 @@ def fetch(
967993else :
968994args = [refspec ]
969995
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+
9701004proc = self .repo .git .fetch (
9711005"--" ,self ,* args ,as_process = True ,with_stdout = False ,universal_newlines = True ,v = verbose ,** kwargs
9721006 )
@@ -980,6 +1014,8 @@ def pull(
9801014refspec :Union [str ,List [str ],None ]= None ,
9811015progress :Union [RemoteProgress ,"UpdateProgress" ,None ]= None ,
9821016kill_after_timeout :Union [None ,float ]= None ,
1017+ allow_unsafe_protocols :bool = False ,
1018+ allow_unsafe_options :bool = False ,
9831019** kwargs :Any ,
9841020 )-> IterableList [FetchInfo ]:
9851021"""Pull changes from the given branch, being the same as a fetch followed
@@ -994,6 +1030,15 @@ def pull(
9941030# No argument refspec, then ensure the repo's config has a fetch refspec.
9951031self ._assert_refspec ()
9961032kwargs = 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+
9971042proc = self .repo .git .pull (
9981043"--" ,self ,refspec ,with_stdout = False ,as_process = True ,universal_newlines = True ,v = True ,** kwargs
9991044 )
@@ -1007,6 +1052,8 @@ def push(
10071052refspec :Union [str ,List [str ],None ]= None ,
10081053progress :Union [RemoteProgress ,"UpdateProgress" ,Callable [...,RemoteProgress ],None ]= None ,
10091054kill_after_timeout :Union [None ,float ]= None ,
1055+ allow_unsafe_protocols :bool = False ,
1056+ allow_unsafe_options :bool = False ,
10101057** kwargs :Any ,
10111058 )-> PushInfoList :
10121059"""Push changes from source branch in refspec to target branch in refspec.
@@ -1037,6 +1084,15 @@ def push(
10371084 be 0.
10381085 Call ``.raise_if_error()`` on the returned object to raise on any failure."""
10391086kwargs = 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+
10401096proc = self .repo .git .push (
10411097"--" ,
10421098self ,