diff --git a/poetry/core/vcs/git.py b/poetry/core/vcs/git.py index 220b5018c..1987f1974 100644 --- a/poetry/core/vcs/git.py +++ b/poetry/core/vcs/git.py @@ -118,6 +118,11 @@ ] +class GitError(RuntimeError): + + pass + + class ParsedUrl: def __init__( self, @@ -243,7 +248,9 @@ def config(self) -> GitConfig: return self._config def clone(self, repository: str, dest: Path) -> str: - return self.run("clone", "--recurse-submodules", repository, str(dest)) + self._check_parameter(repository) + + return self.run("clone", "--recurse-submodules", "--", repository, str(dest)) def checkout(self, rev: str, folder: Optional[Path] = None) -> str: args = [] @@ -258,6 +265,8 @@ def checkout(self, rev: str, folder: Optional[Path] = None) -> str: folder.as_posix(), ] + self._check_parameter(rev) + args += ["checkout", rev] return self.run(*args) @@ -267,6 +276,8 @@ def rev_parse(self, rev: str, folder: Optional[Path] = None) -> str: if folder is None and self._work_dir: folder = self._work_dir + self._check_parameter(rev) + # We need "^0" (an alternative to "^{commit}") to ensure that the # commit SHA of the commit the tag points to is returned, even in # the case of annotated tags. @@ -337,3 +348,10 @@ def run(self, *args: Any, **kwargs: Any) -> str: .decode() .strip() ) + + def _check_parameter(self, parameter: str) -> str: + """ + Checks a git parameter to avoid unwanted code execution. + """ + if parameter.strip().startswith("-"): + raise GitError(f"Invalid Git parameter: {parameter}") diff --git a/tests/vcs/test_vcs.py b/tests/vcs/test_vcs.py index 52cf32d68..4d22c9fa2 100644 --- a/tests/vcs/test_vcs.py +++ b/tests/vcs/test_vcs.py @@ -1,6 +1,9 @@ +from pathlib import Path + import pytest from poetry.core.vcs.git import Git +from poetry.core.vcs.git import GitError from poetry.core.vcs.git import GitUrl from poetry.core.vcs.git import ParsedUrl @@ -348,3 +351,18 @@ def test_parse_url_should_fail(): with pytest.raises(ValueError): ParsedUrl.parse(url) + + +def test_git_clone_raises_error_on_invalid_repository(): + with pytest.raises(GitError): + Git().clone("-u./payload", Path("foo")) + + +def test_git_checkout_raises_error_on_invalid_repository(): + with pytest.raises(GitError): + Git().checkout("-u./payload") + + +def test_git_rev_parse_raises_error_on_invalid_repository(): + with pytest.raises(GitError): + Git().rev_parse("-u./payload")