Update dependency gitpython to v3.1.47 [SECURITY]#1100
Open
renovate[bot] wants to merge 1 commit intomainfrom
Open
Update dependency gitpython to v3.1.47 [SECURITY]#1100renovate[bot] wants to merge 1 commit intomainfrom
renovate[bot] wants to merge 1 commit intomainfrom
Conversation
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.41→==3.1.47GitPython 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 #1912DiffFuzz Target by @DaveLak in #1914.gitsubdir as anothersafe.directoryon Cygwin CI by @EliahKagan in #1916validate-pyprojectby @Borda in #1921fuzz_submoduleFuzzer by @DaveLak in #1926end-of-file-fixerby @Borda in #1920fuzz_submoduleCausing a lot of False Alarms in the OSS-Fuzz Bug Tracker by @DaveLak in #1950PermissionErrorexceptions that crash fuzzer by @DaveLak in #1951New Contributors
Full Changelog: gitpython-developers/GitPython@3.1.43...3.1.44
v3.1.43Compare Source
Particularly Important Changes
These are likely to affect you, please do take a careful look.
Other Changes
repo.blameandrepo.blame_incrementalnow acceptNoneas therevparameter. by @Gaubbe in #1846create_patch=Trueby @can-taslicukur in #1832flake8withruffcheck by @Borda in #1862ruff-formatby @Borda in #1865Submodule.__init__parent_commit parameter by @EliahKagan in #1877New Contributors
Full Changelog: gitpython-developers/GitPython@3.1.42...3.1.43
v3.1.42Compare Source
What's Changed
New Contributors
Full Changelog: gitpython-developers/GitPython@3.1.41...3.1.42
Configuration
📅 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.