Skip to content

Security: Force positional arguments to always be arguments to avoid options injection #1517

Closed
@stsewd

Description

@stsewd

This is somehow related to #1515, but as a more broad problem. Gitpython exposes some methods to interact with the git program, but gitpython fails to validate/escape the arguments (user-input), resulting in the user being able to pass options to the final git command, this doesn't seem bad, but git exposes some options (--upload-pack and --receive-pack) that can lead to remote code execution.

One example is the clone() method, it receives a path

path: PathLike,

But an option can be passed as well, leading to RCE, a full working example is:

import git
r = git.Repo.init('/tmp/test', bare=True)
r.clone("--upload-pack=touch /tmp/pwn")

A usual solution is to add -- before any user-input arguments, forcing them to always be taken as positional arguments and not options, but there are commands like git checkout that make special use of --, git mentions the --end-of-options option https://git-scm.com/docs/gitcli/ as an alias for -- for cases like that, but that option isn't available for git checkout 🙃

Other options could be:

  • To have a list of commands (like checkout) to not add --
  • Check all command calls and add -- manually to each one, for example

    GitPython/git/repo/base.py

    Lines 1170 to 1180 in 17ff263

    proc = git.clone(
    multi,
    Git.polish_url(str(url)),
    clone_path,
    with_extended_output=True,
    as_process=True,
    v=True,
    universal_newlines=True,
    **add_progress(kwargs, git, progress),
    )
    if progress:

    that would be git.clone(multi, '--', ...)

ref #1515 (comment).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions