diff --git a/CHANGES b/CHANGES index da3752c21..e546ef7db 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,12 @@ - _Add your latest changes from PRs here_ +### Potential command injection via mercurial URLs + +- By setting a mercurial URL with an alias it is possible to execute arbitrary shell commands via + `.obtain()` or in the case of uncloned destinations, `.update_repo()`. (#306, credit: Alessio + Della Libera) + ### Development - Run pyupgrade formatting (#305) diff --git a/libvcs/hg.py b/libvcs/hg.py index a89ea82ac..5ec53e03f 100644 --- a/libvcs/hg.py +++ b/libvcs/hg.py @@ -26,7 +26,9 @@ def __init__(self, url, repo_dir, **kwargs): def obtain(self): self.ensure_dir() - self.run(["clone", "--noupdate", "-q", self.url, self.path]) + # Double hyphens between [OPTION]... -- SOURCE [DEST] prevent command injections + # via aliases + self.run(["clone", "--noupdate", "-q", "--", self.url, self.path]) self.run(["update", "-q"]) def get_revision(self): diff --git a/tests/test_hg.py b/tests/test_hg.py index a73f7372a..7d267f90c 100644 --- a/tests/test_hg.py +++ b/tests/test_hg.py @@ -5,7 +5,7 @@ import pytest -from libvcs.shortcuts import create_repo_from_pip_url +from libvcs.shortcuts import create_repo, create_repo_from_pip_url from libvcs.util import run, which if not which("hg"): @@ -72,3 +72,28 @@ def test_repo_mercurial(tmp_path: pathlib.Path, repos_path, hg_remote): ) assert mercurial_repo.get_revision() == test_repo_revision + + +def test_vulnerability_2022_03_12_command_injection( + monkeypatch: pytest.MonkeyPatch, + user_path: pathlib.Path, + tmp_path: pathlib.Path, + hg_remote, +): + """Prevent hg aliases from executed arbitrary commands via URLs. + + As of 0.11 this code path is/was only executed via .obtain(), so this only would + effect explicit invocation of .object() or update_repo() of uncloned destination. + """ + random_dir = tmp_path / "random" + random_dir.mkdir() + monkeypatch.chdir(str(random_dir)) + mercurial_repo = create_repo( + url="--config=alias.clone=!touch ./HELLO", vcs="hg", repo_dir="./" + ) + with pytest.raises(Exception): + mercurial_repo.update_repo() + + assert not pathlib.Path( + random_dir / "HELLO" + ).exists(), "Prevent command injection in hg aliases" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy