new file mode 100644
@@ -0,0 +1,39 @@
+From b324c831cbc02c82b99c18113b622d03539d23cd Mon Sep 17 00:00:00 2001
+From: Byron <sebastian.thiel@icloud.com>
+Date: Tue, 4 Aug 2026 11:07:02 +0200
+Subject: [PATCH] Initialize submodule repository before handled failures
+
+<!-- agent -->
+Direct recursive updates with keep_going could swallow an invalid-name
+validation error and then access mrepo before assignment. Reproduce that
+path and initialize mrepo before validation so recursion is safely skipped.
+
+Git baseline: submodule.c at 883a47ef6496c96a5d6132ed8c87fcd44ebf8d1a
+validates submodule paths before operating on them.
+
+CVE: CVE-2026-76222
+Upstream-Status: Backport [https://github.com/gitpython-developers/GitPython/commit/b324c831cbc02c82b99c18113b622d03539d23cd]
+
+Backport Changes:
+- Omitted .basedpyright/baseline.json and test/test_submodule.py because the
+ current PyPI source archive does not include these development files, and the
+ python3-git recipe does not run the test suite.
+
+Assisted-by: GPT 5.6
+Co-authored-by: GPT 5.6 <codex@openai.com>
+(cherry picked from commit b324c831cbc02c82b99c18113b622d03539d23cd)
+Signed-off-by: Yogita Urade <yurade@cisco.com>
+---
+ git/objects/submodule/base.py | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/git/objects/submodule/base.py b/git/objects/submodule/base.py
+index 658259cd2..9b1eb0e02 100644
+--- a/git/objects/submodule/base.py
++++ b/git/objects/submodule/base.py
+@@ -743,4 +743,2 @@
+- # To keep things plausible in dry-run mode.
+- if dry_run:
+- mrepo = None
++ mrepo = None
+ # END init mrepo
new file mode 100644
@@ -0,0 +1,120 @@
+From 3f48614f5b02f67daf311a6681e6e5090a7f7dc3 Mon Sep 17 00:00:00 2001
+From: Byron <sebastian.thiel@icloud.com>
+Date: Sat, 1 Aug 2026 04:47:40 +0200
+Subject: [PATCH] Validate submodule names before filesystem operations
+
+<!-- agent -->
+Submodule names read from .gitmodules can influence the separate Git directory
+path. Reject empty names, absolute or drive-qualified names, and parent
+components with either path separator.
+
+Validate before constructing module paths and before opening or mutating
+existing checkouts, so a repository initialized by an older vulnerable version
+cannot bypass the guard. Validate programmatic add and rename inputs before
+making changes as well.
+
+Advisory: GHSA-hmq2-w58f-27jc
+
+CVE: CVE-2026-76222
+Upstream-Status: Backport [https://github.com/gitpython-developers/GitPython/commit/e4b8e7d026ca6abb4cf604f8e77093432ce23c06]
+
+Backport Changes:
+- Omitted test/test_submodule.py because the current PyPI source archive
+ does not include the test suite, and the python3-git recipe does not run it.
+
+Assisted-by: GPT 5.6
+Co-authored-by: GPT 5.6 <codex@openai.com>
+(cherry picked from commit e4b8e7d026ca6abb4cf604f8e77093432ce23c06)
+Signed-off-by: Yogita Urade <yurade@cisco.com>
+(cherry picked from commit 14bdaeca511c6ba89f91d4d416f69c1efbcf204f)
+Signed-off-by: Yogita Urade <yurade@cisco.com>
+---
+ git/objects/submodule/base.py | 23 ++++++++++++++++++++++-
+ 1 file changed, 22 insertions(+), 1 deletion(-)
+
+diff --git a/git/objects/submodule/base.py b/git/objects/submodule/base.py
+index 43e0ec9a..a4e0077c 100644
+--- a/git/objects/submodule/base.py
++++ b/git/objects/submodule/base.py
+@@ -6,6 +6,7 @@ __all__ = ["Submodule", "UpdateProgress"]
+ import gc
+ from io import BytesIO
+ import logging
++import ntpath
+ import os
+ import os.path as osp
+ import stat
+@@ -300,10 +301,21 @@ class Submodule(IndexObject, TraversableIterableObj):
+ parser.set_submodule(self)
+ return SectionConstraint(parser, sm_section(self.name))
+
++ @classmethod
++ def _validated_name(cls, name: str) -> str:
++ if (
++ not name
++ or name.startswith(("/", "\\"))
++ or ntpath.splitdrive(name)[0]
++ or ".." in name.replace("\\", "/").split("/")
++ ):
++ raise ValueError("Invalid submodule name %r" % name)
++ return name
++
+ @classmethod
+ def _module_abspath(cls, parent_repo: "Repo", path: PathLike, name: str) -> PathLike:
+ if cls._need_gitfile_submodules(parent_repo.git):
+- return osp.join(parent_repo.git_dir, "modules", name)
++ return osp.join(parent_repo.git_dir, "modules", cls._validated_name(name))
+ if parent_repo.working_tree_dir:
+ return osp.join(parent_repo.working_tree_dir, path)
+ raise NotADirectoryError()
+@@ -516,6 +528,7 @@ class Submodule(IndexObject, TraversableIterableObj):
+ raise InvalidGitRepositoryError("Cannot add submodules to bare repositories")
+ # END handle bare repos
+
++ cls._validated_name(name)
+ path = cls._to_relative_path(repo, path)
+
+ # Ensure we never put backslashes into the URL, as might happen on Windows.
+@@ -733,6 +746,8 @@ class Submodule(IndexObject, TraversableIterableObj):
+ # END init mrepo
+
+ try:
++ self._validated_name(self.name)
++
+ # ENSURE REPO IS PRESENT AND UP-TO-DATE
+ #######################################
+ try:
+@@ -999,6 +1014,7 @@ class Submodule(IndexObject, TraversableIterableObj):
+ raise ValueError("You must specify to move at least the module or the configuration of the submodule")
+ # END handle input
+
++ self._validated_name(self.name)
+ module_checkout_path = self._to_relative_path(self.repo, module_path)
+
+ # VERIFY DESTINATION
+@@ -1139,6 +1155,7 @@ class Submodule(IndexObject, TraversableIterableObj):
+ raise ValueError("Need to specify to delete at least the module, or the configuration")
+ # END handle parameters
+
++ self._validated_name(self.name)
+ # Recursively remove children of this submodule.
+ nc = 0
+ for csm in self.children():
+@@ -1365,6 +1382,9 @@ class Submodule(IndexObject, TraversableIterableObj):
+ if self.name == new_name:
+ return self
+
++ self._validated_name(self.name)
++ self._validated_name(new_name)
++
+ # .git/config
+ with self.repo.config_writer() as pw:
+ # As we ourselves didn't write anything about submodules into the parent
+@@ -1412,6 +1432,7 @@ class Submodule(IndexObject, TraversableIterableObj):
+ If a repository was not available.
+ This could also mean that it was not yet initialized.
+ """
++ self._validated_name(self.name)
+ module_checkout_abspath = self.abspath
+ try:
+ repo = git.Repo(module_checkout_abspath)
new file mode 100644
@@ -0,0 +1,47 @@
+From 4a0dfd9b336dd9332b347c3af8e8ec536017d863 Mon Sep 17 00:00:00 2001
+From: Byron <sebastian.thiel@icloud.com>
+Date: Tue, 4 Aug 2026 10:08:41 +0200
+Subject: [PATCH] Validate submodule names on every module path branch
+
+<!-- agent -->
+_module_abspath only validated names when Git used separate gitfile
+submodule directories, so legacy Git behavior could accept the same invalid
+name. Validate before selecting the Git-version-dependent path branch and
+cover the legacy branch explicitly.
+
+Git baseline: submodule.c at 883a47ef6496c96a5d6132ed8c87fcd44ebf8d1a
+validates submodule paths before filesystem operations.
+
+CVE: CVE-2026-76222
+Upstream-Status: Backport [https://github.com/gitpython-developers/GitPython/commit/4299c990e1ca21896f9485277caf7bb0ae5b404c]
+
+Backport Changes:
+- Omitted test/test_submodule.py because the current PyPI source
+ archive does not include the test suite and the python3-git
+ recipe does not run it.
+
+Assisted-by: GPT 5.6
+Co-authored-by: GPT 5.6 <codex@openai.com>
+(cherry picked from commit 4299c990e1ca21896f9485277caf7bb0ae5b404c)
+Signed-off-by: Yogita Urade <yurade@cisco.com>
+(cherry picked from commit 8d0b9b6ab8dea412499e21fb65a4e9eacb0a5ae0)
+Signed-off-by: Yogita Urade <yurade@cisco.com>
+---
+ git/objects/submodule/base.py | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/git/objects/submodule/base.py b/git/objects/submodule/base.py
+index a4e0077c..d25df367 100644
+--- a/git/objects/submodule/base.py
++++ b/git/objects/submodule/base.py
+@@ -314,8 +314,9 @@ class Submodule(IndexObject, TraversableIterableObj):
+
+ @classmethod
+ def _module_abspath(cls, parent_repo: "Repo", path: PathLike, name: str) -> PathLike:
++ name = cls._validated_name(name)
+ if cls._need_gitfile_submodules(parent_repo.git):
+- return osp.join(parent_repo.git_dir, "modules", cls._validated_name(name))
++ return osp.join(parent_repo.git_dir, "modules", name)
+ if parent_repo.working_tree_dir:
+ return osp.join(parent_repo.working_tree_dir, path)
+ raise NotADirectoryError()
@@ -40,6 +40,9 @@ SRC_URI += "file://CVE-2026-42284.patch \
file://CVE-2026-76219.patch \
file://CVE-2026-76218.patch \
file://CVE-2026-76217.patch \
+ file://CVE-2026-76222_p1.patch \
+ file://CVE-2026-76222-regression.patch \
+ file://CVE-2026-76222_p2.patch \
"
SRC_URI[sha256sum] = "35f314a9f878467f5453cc1fee295c3e18e52f1b99f10f6cf5b1682e968a9e7c"
This patch applies the upstream fix as referenced in [4], using the commit shown in [1], regression fix in [2] and follow-up fix in [3]. [1] https://github.com/gitpython-developers/GitPython/commit/e4b8e7d026ca6abb4cf604f8e77093432ce23c06 [2] https://github.com/gitpython-developers/GitPython/commit/b324c831cbc02c82b99c18113b622d03539d23cd [3] https://github.com/gitpython-developers/GitPython/commit/4299c990e1ca21896f9485277caf7bb0ae5b404c [4] https://nvd.nist.gov/vuln/detail/CVE-2026-76222 Signed-off-by: Yogita Urade <yurade@cisco.com> --- .../CVE-2026-76222-regression.patch | 39 ++++++ .../python3-git/CVE-2026-76222_p1.patch | 120 ++++++++++++++++++ .../python3-git/CVE-2026-76222_p2.patch | 47 +++++++ .../python/python3-git_3.1.43.bb | 3 + 4 files changed, 209 insertions(+) create mode 100644 meta/recipes-devtools/python/python3-git/CVE-2026-76222-regression.patch create mode 100644 meta/recipes-devtools/python/python3-git/CVE-2026-76222_p1.patch create mode 100644 meta/recipes-devtools/python/python3-git/CVE-2026-76222_p2.patch