Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sanitize Mercurial branch information before checkout. #1689

Merged
merged 2 commits into from Jun 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions HISTORY.md
Expand Up @@ -2,6 +2,8 @@

History is important, but our current roadmap can be found [here](https://github.com/cookiecutter/cookiecutter/projects)

## 2.1.1 (unreleased)

## 2.1.0 (2022-05-30)

### Changes
Expand Down
14 changes: 9 additions & 5 deletions cookiecutter/vcs.py
Expand Up @@ -98,22 +98,26 @@ def clone(repo_url, checkout=None, clone_to_dir='.', no_input=False):
stderr=subprocess.STDOUT,
)
if checkout is not None:
checkout_params = [checkout]
# Avoid Mercurial "--config" and "--debugger" injection vulnerability
if repo_type == "hg":
checkout_params.insert(0, "--")
subprocess.check_output( # nosec
[repo_type, 'checkout', checkout],
[repo_type, 'checkout', *checkout_params],
cwd=repo_dir,
stderr=subprocess.STDOUT,
)
except subprocess.CalledProcessError as clone_error:
output = clone_error.output.decode('utf-8')
if 'not found' in output.lower():
raise RepositoryNotFound(
'The repository {} could not be found, '
'have you made a typo?'.format(repo_url)
f'The repository {repo_url} could not be found, '
'have you made a typo?'
)
if any(error in output for error in BRANCH_ERRORS):
raise RepositoryCloneFailed(
'The {} branch of repository {} could not found, '
'have you made a typo?'.format(checkout, repo_url)
f'The {checkout} branch of repository '
f'{repo_url} could not found, have you made a typo?'
)
logger.error('git clone failed with error: %s', output)
raise
Expand Down
18 changes: 13 additions & 5 deletions tests/vcs/test_clone.py
Expand Up @@ -122,8 +122,16 @@ def test_clone_should_invoke_vcs_command(
mock_subprocess.assert_any_call(
[repo_type, 'clone', repo_url], cwd=str(clone_dir), stderr=subprocess.STDOUT
)

branch_info = [branch]
# We sanitize branch information for Mercurial
if repo_type == "hg":
branch_info.insert(0, "--")

mock_subprocess.assert_any_call(
[repo_type, 'checkout', branch], cwd=expected_repo_dir, stderr=subprocess.STDOUT
[repo_type, 'checkout', *branch_info],
cwd=expected_repo_dir,
stderr=subprocess.STDOUT,
)


Expand Down Expand Up @@ -151,8 +159,8 @@ def test_clone_handles_repo_typo(mocker, clone_dir, error_message):
vcs.clone(repository_url, clone_to_dir=str(clone_dir), no_input=True)

assert str(err.value) == (
'The repository {} could not be found, have you made a typo?'
).format(repository_url)
f'The repository {repository_url} could not be found, have you made a typo?'
)


@pytest.mark.parametrize(
Expand Down Expand Up @@ -182,8 +190,8 @@ def test_clone_handles_branch_typo(mocker, clone_dir, error_message):

assert str(err.value) == (
'The unknown_branch branch of repository '
'{} could not found, have you made a typo?'
).format(repository_url)
f'{repository_url} could not found, have you made a typo?'
)


def test_clone_unknown_subprocess_error(mocker, clone_dir):
Expand Down