mirror of
https://git.yoctoproject.org/poky
synced 2026-09-12 06:49:32 +02:00
python3-git: fix CVE-2026-44243
This patch applies the upstream 3.1.48 backport for CVE-2026-44243. The upstream fix merge is referenced in [1], and the public CVE advisory is referenced in [2]. The individual backported commits are referenced in [3] and [4]. [1]dbfa264764[2] https://nvd.nist.gov/vuln/detail/CVE-2026-44243 [3]25ba54dd3f[4]4af8463cca(From OE-Core rev: 0853d0c72e96a3c4e3a5329589a9aa151e2f2c46) Signed-off-by: Darsh Kelaiya <dkelaiya@cisco.com> Signed-off-by: Yoann Congal <yoann.congal@smile.fr> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
committed by
Richard Purdie
parent
1e39c2a5e3
commit
96afd71237
136
meta/recipes-devtools/python/python3-git/CVE-2026-44243_p1.patch
Normal file
136
meta/recipes-devtools/python/python3-git/CVE-2026-44243_p1.patch
Normal file
@@ -0,0 +1,136 @@
|
||||
From fcd8d016816696780c0dc96dacbe48fc10df80f6 Mon Sep 17 00:00:00 2001
|
||||
From: "GPT 5.5" <codex@openai.com>
|
||||
Date: Tue, 28 Apr 2026 09:17:31 +0800
|
||||
Subject: [PATCH] prevent out-of-repo access when manipulating references.
|
||||
|
||||
This previously made it possible to create, modify and delete files outside outside
|
||||
of the repository, which is a problem if inputs aren't trusted.
|
||||
|
||||
CVE: CVE-2026-44243
|
||||
Upstream-Status: Backport [https://github.com/gitpython-developers/GitPython/commit/25ba54dd3fb374b8fade7de4be1ac2ac84722190]
|
||||
|
||||
Backport Changes:
|
||||
- Omit regression tests because the Scarthgap PyPI source
|
||||
archive does not include the upstream test suite.
|
||||
|
||||
Co-authored-by: Sebastian Thiel <sebastian.thiel@icloud.com>
|
||||
(cherry picked from commit 25ba54dd3fb374b8fade7de4be1ac2ac84722190)
|
||||
Signed-off-by: Darsh Kelaiya <dkelaiya@cisco.com>
|
||||
---
|
||||
git/refs/log.py | 2 +-
|
||||
git/refs/remote.py | 5 +++--
|
||||
git/refs/symbolic.py | 37 +++++++++++++++++++++++++++++++------
|
||||
3 files changed, 35 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/git/refs/log.py b/git/refs/log.py
|
||||
index e45798d8..29293f4a 100644
|
||||
--- a/git/refs/log.py
|
||||
+++ b/git/refs/log.py
|
||||
@@ -204,7 +204,7 @@ class RefLog(List[RefLogEntry], Serializable):
|
||||
file though.
|
||||
:param ref: SymbolicReference instance
|
||||
"""
|
||||
- return osp.join(ref.repo.git_dir, "logs", to_native_path(ref.path))
|
||||
+ return to_native_path(ref._get_validated_reflog_path(ref.repo, ref.path))
|
||||
|
||||
@classmethod
|
||||
def iter_entries(cls, stream: Union[str, "BytesIO", mmap]) -> Iterator[RefLogEntry]:
|
||||
diff --git a/git/refs/remote.py b/git/refs/remote.py
|
||||
index 59d02a75..e50c54eb 100644
|
||||
--- a/git/refs/remote.py
|
||||
+++ b/git/refs/remote.py
|
||||
@@ -64,12 +64,13 @@ class RemoteReference(Head):
|
||||
# are generally ignored in the refs/ folder. We don't though
|
||||
# and delete remainders manually.
|
||||
for ref in refs:
|
||||
+ cls._check_ref_name_valid(ref.path)
|
||||
try:
|
||||
- os.remove(os.path.join(repo.common_dir, ref.path))
|
||||
+ os.remove(cls._get_validated_path(repo.common_dir, ref.path))
|
||||
except OSError:
|
||||
pass
|
||||
try:
|
||||
- os.remove(os.path.join(repo.git_dir, ref.path))
|
||||
+ os.remove(cls._get_validated_path(repo.git_dir, ref.path))
|
||||
except OSError:
|
||||
pass
|
||||
# END for each ref
|
||||
diff --git a/git/refs/symbolic.py b/git/refs/symbolic.py
|
||||
index 31f959ac..d5c18290 100644
|
||||
--- a/git/refs/symbolic.py
|
||||
+++ b/git/refs/symbolic.py
|
||||
@@ -109,6 +109,32 @@ class SymbolicReference:
|
||||
def abspath(self) -> PathLike:
|
||||
return join_path_native(_git_dir(self.repo, self.path), self.path)
|
||||
|
||||
+ @staticmethod
|
||||
+ def _get_validated_path(base: PathLike, path: PathLike) -> str:
|
||||
+ path = os.fspath(path)
|
||||
+ base_path = os.path.realpath(os.fspath(base))
|
||||
+ abs_path = os.path.realpath(os.path.join(base_path, path))
|
||||
+ try:
|
||||
+ common_path = os.path.commonpath([base_path, abs_path])
|
||||
+ except ValueError as e:
|
||||
+ raise ValueError("Reference path %r escapes the repository" % path) from e
|
||||
+ if os.path.normcase(common_path) != os.path.normcase(base_path):
|
||||
+ raise ValueError("Reference path %r escapes the repository" % path)
|
||||
+ return abs_path
|
||||
+
|
||||
+ @classmethod
|
||||
+ def _get_validated_ref_path(cls, repo: "Repo", path: PathLike) -> str:
|
||||
+ """Return the absolute filesystem path for a ref after validating it."""
|
||||
+ cls._check_ref_name_valid(path)
|
||||
+ ref_path = os.fspath(path)
|
||||
+ return cls._get_validated_path(_git_dir(repo, ref_path), ref_path)
|
||||
+
|
||||
+ @classmethod
|
||||
+ def _get_validated_reflog_path(cls, repo: "Repo", path: PathLike) -> str:
|
||||
+ """Return the absolute filesystem path for a reflog after validating it."""
|
||||
+ cls._check_ref_name_valid(path)
|
||||
+ return cls._get_validated_path(os.path.join(repo.git_dir, "logs"), path)
|
||||
+
|
||||
@classmethod
|
||||
def _get_packed_refs_path(cls, repo: "Repo") -> str:
|
||||
return os.path.join(repo.common_dir, "packed-refs")
|
||||
@@ -442,7 +468,7 @@ class SymbolicReference:
|
||||
# END handle non-existing
|
||||
# END retrieve old hexsha
|
||||
|
||||
- fpath = self.abspath
|
||||
+ fpath = self._get_validated_ref_path(self.repo, self.path)
|
||||
assure_directory_exists(fpath, is_file=True)
|
||||
|
||||
lfd = LockedFD(fpath)
|
||||
@@ -571,7 +597,7 @@ class SymbolicReference:
|
||||
Alternatively the symbolic reference to be deleted.
|
||||
"""
|
||||
full_ref_path = cls.to_full_path(path)
|
||||
- abs_path = os.path.join(repo.common_dir, full_ref_path)
|
||||
+ abs_path = cls._get_validated_ref_path(repo, full_ref_path)
|
||||
if os.path.exists(abs_path):
|
||||
os.remove(abs_path)
|
||||
else:
|
||||
@@ -635,9 +661,8 @@ class SymbolicReference:
|
||||
corresponding object and a detached symbolic reference will be created
|
||||
instead.
|
||||
"""
|
||||
- git_dir = _git_dir(repo, path)
|
||||
full_ref_path = cls.to_full_path(path)
|
||||
- abs_ref_path = os.path.join(git_dir, full_ref_path)
|
||||
+ abs_ref_path = cls._get_validated_ref_path(repo, full_ref_path)
|
||||
|
||||
# Figure out target data.
|
||||
target = reference
|
||||
@@ -724,8 +749,8 @@ class SymbolicReference:
|
||||
if self.path == new_path:
|
||||
return self
|
||||
|
||||
- new_abs_path = os.path.join(_git_dir(self.repo, new_path), new_path)
|
||||
- cur_abs_path = os.path.join(_git_dir(self.repo, self.path), self.path)
|
||||
+ new_abs_path = self._get_validated_ref_path(self.repo, new_path)
|
||||
+ cur_abs_path = self._get_validated_ref_path(self.repo, self.path)
|
||||
if os.path.isfile(new_abs_path):
|
||||
if not force:
|
||||
# If they point to the same file, it's not an error.
|
||||
--
|
||||
2.35.6
|
||||
@@ -0,0 +1,86 @@
|
||||
From 2d1f681978b51ffff0db57cf89b0bcd6bffc7418 Mon Sep 17 00:00:00 2001
|
||||
From: "GPT 5.5" <codex@openai.com>
|
||||
Date: Tue, 28 Apr 2026 09:30:41 +0800
|
||||
Subject: [PATCH] address review feedback and CI failures
|
||||
|
||||
Consolidate follow-up fixes from review and CI:
|
||||
|
||||
- fix lint and mypy issues in reference log path handling
|
||||
- validate remote reference paths before invoking git branch deletion
|
||||
- add symlink escape coverage where realpath resolves symlinks
|
||||
- ensure temporary test repositories release git resources during cleanup
|
||||
|
||||
CVE: CVE-2026-44243
|
||||
Upstream-Status: Backport [https://github.com/gitpython-developers/GitPython/commit/4af8463cca31c2369312fcaa5309dfc30756c7b6]
|
||||
|
||||
Backport Changes:
|
||||
- Keep the 3.1.42 docstring layout and path coercion while
|
||||
applying upstream validation documentation and return type.
|
||||
- Omit regression test updates because the Scarthgap PyPI
|
||||
source archive does not include the upstream test suite.
|
||||
|
||||
Co-authored-by: Sebastian Thiel <sebastian.thiel@icloud.com>
|
||||
(cherry picked from commit 4af8463cca31c2369312fcaa5309dfc30756c7b6)
|
||||
Signed-off-by: Darsh Kelaiya <dkelaiya@cisco.com>
|
||||
---
|
||||
git/refs/log.py | 3 ++-
|
||||
git/refs/remote.py | 4 +++-
|
||||
git/util.py | 2 +-
|
||||
3 files changed, 6 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/git/refs/log.py b/git/refs/log.py
|
||||
index 29293f4a..eef525e7 100644
|
||||
--- a/git/refs/log.py
|
||||
+++ b/git/refs/log.py
|
||||
@@ -21,7 +21,6 @@ from git.util import (
|
||||
file_contents_ro_filepath,
|
||||
)
|
||||
|
||||
-import os.path as osp
|
||||
|
||||
|
||||
# typing ------------------------------------------------------------------
|
||||
@@ -203,6 +202,8 @@ class RefLog(List[RefLogEntry], Serializable):
|
||||
instance would be found. The path is not guaranteed to point to a valid
|
||||
file though.
|
||||
:param ref: SymbolicReference instance
|
||||
+ :raise ValueError:
|
||||
+ If `ref.path` is invalid or escapes the repository's reflog directory.
|
||||
"""
|
||||
return to_native_path(ref._get_validated_reflog_path(ref.repo, ref.path))
|
||||
|
||||
diff --git a/git/refs/remote.py b/git/refs/remote.py
|
||||
index e50c54eb..70eada81 100644
|
||||
--- a/git/refs/remote.py
|
||||
+++ b/git/refs/remote.py
|
||||
@@ -59,12 +59,14 @@ class RemoteReference(Head):
|
||||
kwargs are given for comparability with the base class method as we
|
||||
should not narrow the signature.
|
||||
"""
|
||||
+ for ref in refs:
|
||||
+ cls._check_ref_name_valid(ref.path)
|
||||
+
|
||||
repo.git.branch("-d", "-r", *refs)
|
||||
# The official deletion method will ignore remote symbolic refs - these
|
||||
# are generally ignored in the refs/ folder. We don't though
|
||||
# and delete remainders manually.
|
||||
for ref in refs:
|
||||
- cls._check_ref_name_valid(ref.path)
|
||||
try:
|
||||
os.remove(cls._get_validated_path(repo.common_dir, ref.path))
|
||||
except OSError:
|
||||
diff --git a/git/util.py b/git/util.py
|
||||
index 03d62ffc..5a136d18 100644
|
||||
--- a/git/util.py
|
||||
+++ b/git/util.py
|
||||
@@ -272,7 +272,7 @@ def join_path(a: PathLike, *p: PathLike) -> PathLike:
|
||||
|
||||
if os.name == "nt":
|
||||
|
||||
- def to_native_path_windows(path: PathLike) -> PathLike:
|
||||
+ def to_native_path_windows(path: PathLike) -> str:
|
||||
path = str(path)
|
||||
return path.replace("/", "\\")
|
||||
|
||||
--
|
||||
2.35.6
|
||||
@@ -13,6 +13,8 @@ PYPI_PACKAGE = "GitPython"
|
||||
inherit pypi python_setuptools_build_meta
|
||||
|
||||
SRC_URI += "file://CVE-2026-42284.patch \
|
||||
file://CVE-2026-44243_p1.patch \
|
||||
file://CVE-2026-44243_p2.patch \
|
||||
"
|
||||
SRC_URI[sha256sum] = "2d99869e0fef71a73cbd242528105af1d6c1b108c60dfabd994bf292f76c3ceb"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user