Update dependency GitPython to v3.1.47 [SECURITY]#56
Open
renovate[bot] wants to merge 1 commit intomainfrom
Open
Update dependency GitPython to v3.1.47 [SECURITY]#56renovate[bot] wants to merge 1 commit intomainfrom
renovate[bot] wants to merge 1 commit intomainfrom
Conversation
✅ Deploy Preview for profound-shortbread-97ca2d ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
3fe667a to
62496df
Compare
❌ Deploy Preview for profound-shortbread-97ca2d failed.
|
62496df to
37f9b89
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
==3.1.30→==3.1.47GitPython vulnerable to remote code execution due to insufficient sanitization of input arguments
CVE-2023-40267 / GHSA-pr76-5cm5-w9cj
More information
Details
GitPython before 3.1.32 does not block insecure non-multi options in
cloneandclone_from, making it vulnerable to Remote Code Execution (RCE) due to improper user input validation, which makes it possible to inject a maliciously crafted remote URL into the clone command. Exploiting this vulnerability is possible because the library makes external calls to git without sufficient sanitization of input arguments. NOTE: this issue exists because of an incomplete fix for CVE-2022-24439.Severity
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
GitPython untrusted search path on Windows systems leading to arbitrary code execution
CVE-2023-40590 / GHSA-wfm5-v35h-vwf4
More information
Details
Summary
When resolving a program, Python/Windows look for the current working directory, and after that the PATH environment (see big warning in https://docs.python.org/3/library/subprocess.html#popen-constructor). GitPython defaults to use the
gitcommand, if a user runs GitPython from a repo has agit.exeorgitexecutable, that program will be run instead of the one in the user'sPATH.Details
This is more of a problem on how Python interacts with Windows systems, Linux and any other OS aren't affected by this. But probably people using GitPython usually run it from the CWD of a repo.
The execution of the
gitcommand happens inhttps://github.com/gitpython-developers/GitPython/blob/1c8310d7cae144f74a671cbe17e51f63a830adbf/git/cmd.py#L277
https://github.com/gitpython-developers/GitPython/blob/1c8310d7cae144f74a671cbe17e51f63a830adbf/git/cmd.py#L983-L996
And there are other commands executed that should probably be aware of this problem.
PoC
On a Windows system, create a
git.exeorgitexecutable in any directory, and import or run GitPython from that directoryThe git executable from the current directory will be run.
Impact
An attacker can trick a user to download a repository with a malicious
gitexecutable, if the user runs/imports GitPython from that directory, it allows the attacker to run any arbitrary commands.Possible solutions
C:\\Program Files\\Git\\cmd\\git.EXE(default git path installation).GIT_PYTHON_GIT_EXECUTABLEenvironment variable on Windows systems.GIT_PYTHON_GIT_EXECUTABLEenv var to an absolute path.PATHenvironment variable (suggested by @Byron)Severity
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Untrusted search path under some conditions on Windows allows arbitrary code execution
CVE-2024-22190 / GHSA-2mqj-m65w-jghx
More information
Details
Summary
This issue exists because of an incomplete fix for CVE-2023-40590. On Windows, GitPython uses an untrusted search path if it uses a shell to run
git, as well as when it runsbash.exeto interpret hooks. If either of those features are used on Windows, a maliciousgit.exeorbash.exemay be run from an untrusted repository.Details
Although GitPython often avoids executing programs found in an untrusted search path since 3.1.33, two situations remain where this still occurs. Either can allow arbitrary code execution under some circumstances.
When a shell is used
GitPython can be told to run
gitcommands through a shell rather than as direct subprocesses, by passingshell=Trueto any method that accepts it, or by both settingGit.USE_SHELL = Trueand not passingshell=False. Then the Windowscmd.exeshell process performs the path search, and GitPython does not prevent that shell from finding and runninggitin the current directory.When GitPython runs
gitdirectly rather than through a shell, the GitPython process performs the path search, and currently omits the current directory by settingNoDefaultCurrentDirectoryInExePathin its own environment during thePopencall. Although thecmd.exeshell will honor this environment variable when present, GitPython does not currently pass it into the shell subprocess's environment.Furthermore, because GitPython sets the subprocess CWD to the root of a repository's working tree, using a shell will run a malicious
git.exein an untrusted repository even if GitPython itself is run from a trusted location.This also applies if
Git.executeis called directly withshell=True(or afterGit.USE_SHELL = True) to run any command.When hook scripts are run
On Windows, GitPython uses
bash.exeto run hooks that appear to be scripts. However, unlike when runninggit, no steps are taken to avoid finding and runningbash.exein the current directory.This allows the author of an untrusted fork or branch to cause a malicious
bash.exeto be run in some otherwise safe workflows. An example of such a scenario is if the user installs a trusted hook while on a trusted branch, then switches to an untrusted feature branch (possibly from a fork) to review proposed changes. If the untrusted feature branch contains a maliciousbash.exeand the user's current working directory is the working tree, and the user performs an action that runs the hook, then although the hook itself is uncorrupted, it runs with the maliciousbash.exe.Note that, while
bash.exeis a shell, this is a separate scenario from whengitis run using the unrelated Windowscmd.exeshell.PoC
On Windows, create a
git.exefile in a repository. Then create aRepoobject, and call any method through it (directly or indirectly) that supports theshellkeyword argument withshell=True:The
git.exeexecutable in the repository directory will be run.Or use no
Repoobject, but do it from the location with thegit.exe:The
git.exeexecutable in the current directory will be run.For the scenario with hooks, install a hook in a repository, create a
bash.exefile in the current directory, and perform an operation that causes GitPython to attempt to run the hook:The
bash.exeexecutable in the current directory will be run.Impact
The greatest impact is probably in applications that set
Git.USE_SHELL = Truefor historical reasons. (Undesired console windows had, in the past, been created in some kinds of applications, when it was not used.) Such an application may be vulnerable to arbitrary code execution from a malicious repository, even with no other exacerbating conditions. This is to say that, if a shell is used to rungit, the full effect of CVE-2023-40590 is still present. Furthermore, as noted above, running the application itself from a trusted directory is not a sufficient mitigation.An application that does not direct GitPython to use a shell to run
gitsubprocesses thus avoids most of the risk. However, there is no such straightforward way to prevent GitPython from runningbash.exeto interpret hooks. So while the conditions needed for that to be exploited are more involved, it may be harder to mitigate decisively prior to patching.Possible solutions
A straightforward approach would be to address each bug directly:
NoDefaultCurrentDirectoryInExePathinto the subprocess environment, because in that scenario the subprocess is thecmd.exeshell that itself performs the path search.NoDefaultCurrentDirectoryInExePathin the GitPython process environment during thePopencall made to run hooks with abash.exesubprocess.These need only be done on Windows.
Severity
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:H/VI:H/VA:H/SC:N/SI:N/SA:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
GitPython blind local file inclusion
CVE-2023-41040 / GHSA-cwvm-v4w8-q58c
More information
Details
Summary
In order to resolve some git references, GitPython reads files from the
.gitdirectory, in some places the name of the file being read is provided by the user, GitPython doesn't check if this file is located outside the.gitdirectory. This allows an attacker to make GitPython read any file from the system.Details
This vulnerability is present in
https://github.com/gitpython-developers/GitPython/blob/1c8310d7cae144f74a671cbe17e51f63a830adbf/git/refs/symbolic.py#L174-L175
That code joins the base directory with a user given string without checking if the final path is located outside the base directory.
I was able to exploit it from three places, but there may be more code paths that lead to it:
https://github.com/gitpython-developers/GitPython/blob/1c8310d7cae144f74a671cbe17e51f63a830adbf/git/repo/base.py#L605
https://github.com/gitpython-developers/GitPython/blob/1c8310d7cae144f74a671cbe17e51f63a830adbf/git/repo/base.py#L620
https://github.com/gitpython-developers/GitPython/blob/1c8310d7cae144f74a671cbe17e51f63a830adbf/git/index/base.py#L1353
PoC
Running GitPython within any repo should work, here is an example with the GitPython repo.
Impact
I wasn't able to show the contents of the files (that's why "blind" local file inclusion), depending on how GitPython is being used, this can be used by an attacker for something inoffensive as checking if a file exits, or cause a DoS by making GitPython read a big/infinite file (like
/dev/randomon Linux systems).Possible solutions
A solution would be to check that the final path isn't located outside the
repodirpath (maybe even after resolving symlinks). Maybe there could be other checks in place to make sure that the reference names are valid.Severity
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
GitPython has Command Injection via Git options bypass
GHSA-rpm5-65cw-6hj4
More information
Details
Summary
GitPython blocks dangerous Git options such as
--upload-packand--receive-packby default, but the equivalent Python kwargsupload_packandreceive_packbypass that check. If an application passes attacker-controlled kwargs intoRepo.clone_from(),Remote.fetch(),Remote.pull(), orRemote.push(), this leads to arbitrary command execution even whenallow_unsafe_optionsis left at its default value ofFalse.Details
GitPython explicitly treats helper-command options as unsafe because they can be used to execute arbitrary commands:
git/repo/base.py:145-153marks clone options such as--upload-pack,-u,--config, and-cas unsafe.git/remote.py:535-548marks fetch/pull/push options such as--upload-pack,--receive-pack, and--execas unsafe.The vulnerable API paths check the raw kwarg names before they're its normalized into command-line flags:
Repo.clone_from()checkslist(kwargs.keys())ingit/repo/base.py:1387-1390Remote.fetch()checkslist(kwargs.keys())ingit/remote.py:1070-1071Remote.pull()checkslist(kwargs.keys())ingit/remote.py:1124-1125Remote.push()checkslist(kwargs.keys())ingit/remote.py:1197-1198That validation is performed by
Git.check_unsafe_options()ingit/cmd.py:948-961. The validator correctly blocks option names such asupload-pack,receive-pack, andexec.Later, GitPython converts Python kwargs into Git command-line flags in
Git.transform_kwarg()atgit/cmd.py:1471-1484. During that step, underscore-form kwargs are dashified:upload_pack=...becomes--upload-pack=...receive_pack=...becomes--receive-pack=...Because the unsafe-option check runs before this normalization, underscore-form kwargs bypass the safety check even though they become the exact dangerous Git flags that the code is supposed to reject.
In practice:
remote.fetch(**{"upload-pack": helper})is blocked withUnsafeOptionErrorremote.fetch(upload_pack=helper)is allowed and reaches helper executionThe same bypass works for:
This does not appear to affect every unsafe option. For example,
exec=is already rejected because the raw kwarg nameexecmatches the blocked option name before normalization.Existing tests cover the hyphenated form, not the vulnerable underscore form. For example:
test/test_clone.py:129-136checks{"upload-pack": ...}test/test_remote.py:830-833checks{"upload-pack": ...}test/test_remote.py:968-975checks{"receive-pack": ...}Those tests correctly confirm the literal Git option names are blocked, but they do not exercise the normal Python kwarg spelling that bypasses the guard.
PoC
python3 -m venv .venv-sec .venv-sec/bin/pip install setuptools gitdb source ./.venv-sec/bin/activatecontrol=blockedproof_exists True ...id, working directory, argv, and selected environment variable namesExample output:
This PoC does not require a malicious repository. The PoC uses that fresh blank repository. The only attacker-controlled input is the kwarg that GitPython turns into
--upload-pack.Impact
Who is impacted:
**kwargsWhat the attacker needs to control:
upload_packorreceive_packin the kwargs passed toRepo.clone_from(),Remote.fetch(),Remote.pull(), orRemote.push()From a severity perspective, this could lead to
The highest-risk environments are network-reachable services and automation systems that expose these GitPython kwargs across a trust boundary while relying on the default unsafe-option guard for protection.
Severity
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:HReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
GitPython: Unsafe option check validates multi_options before shlex.split transformation
GHSA-x2qx-6953-8485
More information
Details
Summary
_clone()validatesmulti_optionsas the original list, then executesshlex.split(" ".join(multi_options)). A string like"--branch main --config core.hooksPath=/x"passes validation (starts with--branch), but after split becomes["--branch", "main", "--config", "core.hooksPath=/x"]. Git applies the config and executes attacker hooks during clone.Details
The vulnerable code is in
git/repo/base.pyline 1383:Then validation runs on the original list at line 1390:
Then execution uses the transformed result at line 1392:
The check at
git/cmd.pyline 959 usesstartswith:"--branch main --config ..."does not start with"--config", so it passes. Aftershlex.split,"--config"becomes its own token and reaches git.Also affects
Submodule.update()viaclone_multi_options.PoC
Output:
Impact
Any application passing user input to
multi_optionsinclone_from(),clone(), orSubmodule.update()is vulnerable. Attacker embeds--config core.hooksPath=<dir>inside a string starting with a safe option. Check does not block it. Git executes attacker code. Same class as CVE-2023-40267.Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:HReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Release Notes
gitpython-developers/GitPython (GitPython)
v3.1.47: - with security fixesCompare Source
Advisories
What's Changed
335c0f6to4c63ee6by @dependabot[bot] in #20964c63ee6to5c1b303by @dependabot[bot] in #2106gc.collect()twice intest_renameon Python 3.12 by @EliahKagan in #2109Repo.active_branchresolution for reftable-backed repositories by @Copilot in #2114with_stdout=Falseby @ngie-eign in #2126shlexby @Byron in #2130New Contributors
Full Changelog: gitpython-developers/GitPython@3.1.46...3.1.47
v3.1.46Compare Source
What's Changed
335c0f6to39d7dbfby @dependabot[bot] in #206839d7dbftof8fdfecby @dependabot[bot] in #2071SymbolicReference.referenceproperty by @emmanuel-ferdman in #2074f8fdfecto65321a2by @dependabot[bot] in #2082mypy==1.18.2by @George-Ogden in #2087os.Pathlikeby @George-Ogden in #208665321a2to4c63ee6by @dependabot[bot] in #2093PathlikeObject to Tree by @George-Ogden in #2094New Contributors
Full Changelog: gitpython-developers/GitPython@3.1.45...3.1.46
v3.1.45Compare Source
What's Changed
SECURITY.mdfiles by @EliahKagan in #1992test_installationby @EliahKagan in #2007test_installationxfail on Cygwin CI by @EliahKagan in #2009IndexFile._to_relative_path- fix case where absolute path gets stripped of trailing slash by @kamilkozik7 in #2012uname-cmdthat doesn't point to an executable file by @gcmarx in #2026contents: readworkflow permissions by @EliahKagan in #2033mypycommand on free-threaded Python by @EliahKagan in #2040performanceandperformancetest jobs by @EliahKagan in #2042setuptoolsrequirement statically by @EliahKagan in #2043_safer_popen_windowscomment by @EliahKagan in #2044USE_SHELLwarning helper signature by @EliahKagan in #2045ConfigParserwith whitespace outside the value by @EliahKagan in #2046""handling in ConfigParser by @EliahKagan in #2047\or"are present inside by @EliahKagan in #2048cat_file.pyfixture without site customizations by @EliahKagan in #2052pipby @EliahKagan in #2053test_installationon warnings, and remove deprecated license classifier by @EliahKagan in #2054New Contributors
Full Changelog: gitpython-developers/GitPython@3.1.44...3.1.45
v3.1.44Compare Source
What's Changed
--mixedand paths by @EliahKagan in #1894IndexErrorinGitConfigParserWhen a Quoted Config Value Contains a Trailing New Line by @DaveLak in #1908fuzz_tree.pyHarness With a Better Alternative by @DaveLak in #1910fix->formatby @Borda in [#1912](https://redirect.github.com/gitpython-developers/GitPython/pConfiguration
📅 Schedule: (UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.