More tests · gitpython-developers/GitPython@c8ae33b
@@ -23,6 +23,8 @@
2323GitCommandError,
2424)
2525from git.cmd import Git
26+from pathlib import Path
27+from git.exc import UnsafeOptionError, UnsafeProtocolError
2628from test.lib import (
2729TestBase,
2830with_rw_repo,
@@ -690,6 +692,215 @@ def test_push_error(self, repo):
690692with self.assertRaisesRegex(GitCommandError, "src refspec __BAD_REF__ does not match any"):
691693rem.push("__BAD_REF__")
692694695+@with_rw_repo("HEAD")
696+def test_set_unsafe_url(self, rw_repo):
697+remote = rw_repo.remote("origin")
698+urls = [
699+"ext::sh -c touch% /tmp/pwn",
700+"fd::17/foo",
701+ ]
702+for url in urls:
703+with self.assertRaises(UnsafeProtocolError):
704+remote.set_url(url)
705+706+@with_rw_repo("HEAD")
707+def test_set_unsafe_url_allowed(self, rw_repo):
708+remote = rw_repo.remote("origin")
709+urls = [
710+"ext::sh -c touch% /tmp/pwn",
711+"fd::17/foo",
712+ ]
713+for url in urls:
714+remote.set_url(url, allow_unsafe_protocols=True)
715+assert list(remote.urls)[-1] == url
716+717+@with_rw_repo("HEAD")
718+def test_add_unsafe_url(self, rw_repo):
719+remote = rw_repo.remote("origin")
720+urls = [
721+"ext::sh -c touch% /tmp/pwn",
722+"fd::17/foo",
723+ ]
724+for url in urls:
725+with self.assertRaises(UnsafeProtocolError):
726+remote.add_url(url)
727+728+@with_rw_repo("HEAD")
729+def test_add_unsafe_url_allowed(self, rw_repo):
730+remote = rw_repo.remote("origin")
731+urls = [
732+"ext::sh -c touch% /tmp/pwn",
733+"fd::17/foo",
734+ ]
735+for url in urls:
736+remote.add_url(url, allow_unsafe_protocols=True)
737+assert list(remote.urls)[-1] == url
738+739+@with_rw_repo("HEAD")
740+def test_create_remote_unsafe_url(self, rw_repo):
741+urls = [
742+"ext::sh -c touch% /tmp/pwn",
743+"fd::17/foo",
744+ ]
745+for url in urls:
746+with self.assertRaises(UnsafeProtocolError):
747+Remote.create(rw_repo, "origin", url)
748+749+@with_rw_repo("HEAD")
750+def test_create_remote_unsafe_url_allowed(self, rw_repo):
751+urls = [
752+"ext::sh -c touch% /tmp/pwn",
753+"fd::17/foo",
754+ ]
755+for i, url in enumerate(urls):
756+remote = Remote.create(rw_repo, f"origin{i}", url, allow_unsafe_protocols=True)
757+assert remote.url == url
758+759+@with_rw_repo("HEAD")
760+def test_fetch_unsafe_url(self, rw_repo):
761+remote = rw_repo.remote("origin")
762+urls = [
763+"ext::sh -c touch% /tmp/pwn",
764+"fd::17/foo",
765+ ]
766+for url in urls:
767+with self.assertRaises(UnsafeProtocolError):
768+remote.fetch(url)
769+770+@with_rw_repo("HEAD")
771+def test_fetch_unsafe_url_allowed(self, rw_repo):
772+remote = rw_repo.remote("origin")
773+urls = [
774+"ext::sh -c touch% /tmp/pwn",
775+"fd::17/foo",
776+ ]
777+for url in urls:
778+# The URL will be allowed into the command, but the command will
779+# fail since we don't have that protocol enabled in the Git config file.
780+with self.assertRaises(GitCommandError):
781+remote.fetch(url, allow_unsafe_protocols=True)
782+783+@with_rw_repo("HEAD")
784+def test_fetch_unsafe_options(self, rw_repo):
785+remote = rw_repo.remote("origin")
786+tmp_dir = Path(tempfile.mkdtemp())
787+tmp_file = tmp_dir / "pwn"
788+unsafe_options = [{"upload-pack": f"touch {tmp_file}"}]
789+for unsafe_option in unsafe_options:
790+with self.assertRaises(UnsafeOptionError):
791+remote.fetch(**unsafe_option)
792+793+@with_rw_repo("HEAD")
794+def test_fetch_unsafe_options_allowed(self, rw_repo):
795+remote = rw_repo.remote("origin")
796+tmp_dir = Path(tempfile.mkdtemp())
797+tmp_file = tmp_dir / "pwn"
798+unsafe_options = [{"upload-pack": f"touch {tmp_file}"}]
799+for unsafe_option in unsafe_options:
800+# The options will be allowed, but the command will fail.
801+with self.assertRaises(GitCommandError):
802+remote.fetch(**unsafe_option, allow_unsafe_options=True)
803+804+@with_rw_repo("HEAD")
805+def test_pull_unsafe_url(self, rw_repo):
806+remote = rw_repo.remote("origin")
807+urls = [
808+"ext::sh -c touch% /tmp/pwn",
809+"fd::17/foo",
810+ ]
811+for url in urls:
812+with self.assertRaises(UnsafeProtocolError):
813+remote.pull(url)
814+815+@with_rw_repo("HEAD")
816+def test_pull_unsafe_url_allowed(self, rw_repo):
817+remote = rw_repo.remote("origin")
818+urls = [
819+"ext::sh -c touch% /tmp/pwn",
820+"fd::17/foo",
821+ ]
822+for url in urls:
823+# The URL will be allowed into the command, but the command will
824+# fail since we don't have that protocol enabled in the Git config file.
825+with self.assertRaises(GitCommandError):
826+remote.pull(url, allow_unsafe_protocols=True)
827+828+@with_rw_repo("HEAD")
829+def test_pull_unsafe_options(self, rw_repo):
830+remote = rw_repo.remote("origin")
831+tmp_dir = Path(tempfile.mkdtemp())
832+tmp_file = tmp_dir / "pwn"
833+unsafe_options = [{"upload-pack": f"touch {tmp_file}"}]
834+for unsafe_option in unsafe_options:
835+with self.assertRaises(UnsafeOptionError):
836+remote.pull(**unsafe_option)
837+838+@with_rw_repo("HEAD")
839+def test_pull_unsafe_options_allowed(self, rw_repo):
840+remote = rw_repo.remote("origin")
841+tmp_dir = Path(tempfile.mkdtemp())
842+tmp_file = tmp_dir / "pwn"
843+unsafe_options = [{"upload-pack": f"touch {tmp_file}"}]
844+for unsafe_option in unsafe_options:
845+# The options will be allowed, but the command will fail.
846+with self.assertRaises(GitCommandError):
847+remote.pull(**unsafe_option, allow_unsafe_options=True)
848+849+@with_rw_repo("HEAD")
850+def test_push_unsafe_url(self, rw_repo):
851+remote = rw_repo.remote("origin")
852+urls = [
853+"ext::sh -c touch% /tmp/pwn",
854+"fd::17/foo",
855+ ]
856+for url in urls:
857+with self.assertRaises(UnsafeProtocolError):
858+remote.push(url)
859+860+@with_rw_repo("HEAD")
861+def test_push_unsafe_url_allowed(self, rw_repo):
862+remote = rw_repo.remote("origin")
863+urls = [
864+"ext::sh -c touch% /tmp/pwn",
865+"fd::17/foo",
866+ ]
867+for url in urls:
868+# The URL will be allowed into the command, but the command will
869+# fail since we don't have that protocol enabled in the Git config file.
870+with self.assertRaises(GitCommandError):
871+remote.push(url, allow_unsafe_protocols=True)
872+873+@with_rw_repo("HEAD")
874+def test_push_unsafe_options(self, rw_repo):
875+remote = rw_repo.remote("origin")
876+tmp_dir = Path(tempfile.mkdtemp())
877+tmp_file = tmp_dir / "pwn"
878+unsafe_options = [
879+ {
880+"receive-pack": f"touch {tmp_file}",
881+"exec": f"touch {tmp_file}",
882+ }
883+ ]
884+for unsafe_option in unsafe_options:
885+with self.assertRaises(UnsafeOptionError):
886+remote.push(**unsafe_option)
887+888+@with_rw_repo("HEAD")
889+def test_push_unsafe_options_allowed(self, rw_repo):
890+remote = rw_repo.remote("origin")
891+tmp_dir = Path(tempfile.mkdtemp())
892+tmp_file = tmp_dir / "pwn"
893+unsafe_options = [
894+ {
895+"receive-pack": f"touch {tmp_file}",
896+"exec": f"touch {tmp_file}",
897+ }
898+ ]
899+for unsafe_option in unsafe_options:
900+# The options will be allowed, but the command will fail.
901+with self.assertRaises(GitCommandError):
902+remote.push(**unsafe_option, allow_unsafe_options=True)
903+693904694905class TestTimeouts(TestBase):
695906@with_rw_repo("HEAD", bare=False)