##// END OF EJS Templates
Escape shell command parts for Git backend...
Daniel Anderson -
r4395:a6dfd14d default
parent child Browse files
Show More
@@ -17,6 +17,12 b' import urllib2'
17 import logging
17 import logging
18 import posixpath
18 import posixpath
19 import string
19 import string
20 try:
21 # Python <=2.7
22 from pipes import quote
23 except ImportError:
24 # Python 3.3+
25 from shlex import quote
20
26
21 from dulwich.objects import Tag
27 from dulwich.objects import Tag
22 from dulwich.repo import Repo, NotGitRepository
28 from dulwich.repo import Repo, NotGitRepository
@@ -654,7 +660,7 b' class GitRepository(BaseRepository):'
654 cmd.append('--bare')
660 cmd.append('--bare')
655 elif not update_after_clone:
661 elif not update_after_clone:
656 cmd.append('--no-checkout')
662 cmd.append('--no-checkout')
657 cmd += ['--', '"%s"' % url, '"%s"' % self.path]
663 cmd += ['--', quote(url), self.path]
658 cmd = ' '.join(cmd)
664 cmd = ' '.join(cmd)
659 # If error occurs run_git_command raises RepositoryError already
665 # If error occurs run_git_command raises RepositoryError already
660 self.run_git_command(cmd)
666 self.run_git_command(cmd)
@@ -664,7 +670,7 b' class GitRepository(BaseRepository):'
664 Tries to pull changes from external location.
670 Tries to pull changes from external location.
665 """
671 """
666 url = self._get_url(url)
672 url = self._get_url(url)
667 cmd = ['pull', "--ff-only", url]
673 cmd = ['pull', "--ff-only", quote(url)]
668 cmd = ' '.join(cmd)
674 cmd = ' '.join(cmd)
669 # If error occurs run_git_command raises RepositoryError already
675 # If error occurs run_git_command raises RepositoryError already
670 self.run_git_command(cmd)
676 self.run_git_command(cmd)
@@ -674,13 +680,13 b' class GitRepository(BaseRepository):'
674 Tries to pull changes from external location.
680 Tries to pull changes from external location.
675 """
681 """
676 url = self._get_url(url)
682 url = self._get_url(url)
677 so, se = self.run_git_command('ls-remote -h %s' % url)
683 so, se = self.run_git_command('ls-remote -h %s' % quote(url))
678 refs = []
684 refs = []
679 for line in (x for x in so.splitlines()):
685 for line in (x for x in so.splitlines()):
680 sha, ref = line.split('\t')
686 sha, ref = line.split('\t')
681 refs.append(ref)
687 refs.append(ref)
682 refs = ' '.join(('+%s:%s' % (r, r) for r in refs))
688 refs = ' '.join(('+%s:%s' % (r, r) for r in refs))
683 cmd = '''fetch %s -- %s''' % (url, refs)
689 cmd = '''fetch %s -- %s''' % (quote(url), refs)
684 self.run_git_command(cmd)
690 self.run_git_command(cmd)
685
691
686 def _update_server_info(self):
692 def _update_server_info(self):
@@ -3,6 +3,7 b' from __future__ import with_statement'
3 import os
3 import os
4 import mock
4 import mock
5 import datetime
5 import datetime
6 import urllib2
6 from kallithea.lib.vcs.backends.git import GitRepository, GitChangeset
7 from kallithea.lib.vcs.backends.git import GitRepository, GitChangeset
7 from kallithea.lib.vcs.exceptions import RepositoryError, VCSError, NodeDoesNotExistError
8 from kallithea.lib.vcs.exceptions import RepositoryError, VCSError, NodeDoesNotExistError
8 from kallithea.lib.vcs.nodes import NodeKind, FileNode, DirNode, NodeState
9 from kallithea.lib.vcs.nodes import NodeKind, FileNode, DirNode, NodeState
@@ -26,6 +27,32 b' class GitRepositoryTest(unittest.TestCas'
26 wrong_repo_path = '/tmp/errorrepo'
27 wrong_repo_path = '/tmp/errorrepo'
27 self.assertRaises(RepositoryError, GitRepository, wrong_repo_path)
28 self.assertRaises(RepositoryError, GitRepository, wrong_repo_path)
28
29
30 def test_git_cmd_injection(self):
31 remote_repo_url = 'https://github.com/codeinn/vcs.git'
32 inject_remote = '%s;%s' % (remote_repo_url, '; echo "Cake";')
33 with self.assertRaises(urllib2.URLError):
34 # Should fail because URL will be: https://github.com/codeinn/vcs.git%3B%3B%20echo%20%22Cake%22%3B
35 urlerror_fail_repo = GitRepository(get_new_dir('injection-repo'), src_url=inject_remote, update_after_clone=True, create=True)
36
37 with self.assertRaises(RepositoryError):
38 # Should fail on direct clone call, which as of this writing does not happen outside of class
39 clone_fail_repo = GitRepository(get_new_dir('injection-repo'), create=True)
40 clone_fail_repo.clone(inject_remote, update_after_clone=True,)
41
42 successfully_cloned = GitRepository(get_new_dir('injection-repo'), src_url=remote_repo_url, update_after_clone=True, create=True)
43 # Repo should have been created
44 self.assertFalse(successfully_cloned._repo.bare)
45
46 with self.assertRaises(RepositoryError):
47 # Should fail because URL will be invalid repo
48 inject_remote_var = '%s;%s' % (remote_repo_url, '; echo $PATH;')
49 successfully_cloned.fetch(inject_remote_var)
50
51 with self.assertRaises(RepositoryError):
52 # Should fail because URL will be invalid repo
53 inject_remote_ls = '%s;%s' % (remote_repo_url, '; ls -1 ~;')
54 successfully_cloned.pull(inject_remote_ls)
55
29 def test_repo_clone(self):
56 def test_repo_clone(self):
30 self.__check_for_existing_repo()
57 self.__check_for_existing_repo()
31 repo = GitRepository(TEST_GIT_REPO)
58 repo = GitRepository(TEST_GIT_REPO)
General Comments 0
You need to be logged in to leave comments. Login now