CVE-2026-112406 is an infinite loop vulnerability in the python-pillow library's PDF parser component. Specifically, the flaw occurs in the PdfParser.rewrite_pages() function when processing a PDF file with a cyclic page tree /Parent reference. This causes the library to hang indefinitely at 100% CPU when appending an image to such a PDF using the append=True option. The issue affects Pillow versions from 5.1.0 up to but not including 13.0.0.
A NULL pointer dereference vulnerability exists in the python-pillow Pillow library's Image.merge() function when processing certain single-band images of mode 'I' or 'F'. The function skips validation for band 0, leading to a crash when a crafted file is loaded via the IPTC plugin. This causes a hard crash of the process, not a catchable Python exception.
CVE-2026-112402 is a high-severity double free vulnerability in the python-pillow Pillow library affecting versions prior to 13.0.0. The flaw occurs in the ImagingScaleAffine function during Image.transform() when a memory allocation for a lookup table fails, leading to a double free of the output image's memory. This causes a crash (SIGSEGV) and heap corruption in processes with memory limits or 32-bit environments. The vulnerability has been present since Pillow 1.0 and is fixed in version 13.0.0.
CVE-2026-112392 is a NULL pointer dereference vulnerability in the python-pillow Pillow library affecting versions prior to 13.0.0. The flaw occurs in the ImagingExpand function when applying median, minimum, maximum, or rank filters to zero-width or zero-height images, causing the Python process to crash with a segmentation fault. This happens because the function attempts to read edge pixels without verifying that the image contains any pixels, leading to a NULL pointer dereference. The issue can be triggered by supplying crafted crop coordinates or multi-page TIFF files with zero-length pages. The vulnerability results in denial of service by crashing the process, with no memory corruption or data disclosure. A fix is available in Pillow version 13.0.0.
CVE-2026-112401 is an inefficient algorithmic complexity vulnerability in the python-pillow Pillow library affecting GIF comment processing. The flaw causes Image.open() to consume CPU time quadratically relative to the size of crafted GIF comment extensions, leading to denial-of-service (DoS) via processor exhaustion. This occurs because the code repeatedly concatenates immutable bytes objects without size limits, causing excessive copying. The issue affects Pillow versions from 5.4.0 up to but not including 13.0.0 and was fixed in version 13.0.0.
CVE-2026-112399 is a high-severity vulnerability in the python-pillow Pillow library affecting versions from 8.1.0 up to but not including 13.0.0. It involves excessive memory allocation when opening certain animated PNG (APNG) files with specific disposal operations. The vulnerability causes Pillow's Image.open() to allocate large amounts of memory based on the image dimensions before performing decompression bomb checks, potentially leading to multi-gigabyte memory spikes and process termination by the operating system's out-of-memory killer.
A use-after-free vulnerability exists in the python-pillow Pillow library when saving images as TIFF to an in-memory buffer. If libtiff rejects a tag during encoding, the encoder frees its output buffer but leaves the TIFF handle open. Later, during cleanup, a write occurs into the freed buffer, causing a crash and potential memory corruption. This affects Pillow versions from 11.3.0 up to but not including 13.0.0. The issue can lead to denial of service or potentially remote code execution when processing attacker-influenced images.
Pillow is a Python imaging library. Prior to 13.0.0, Pillow's P;2L and P;4L raw decoders can read past the end of an input buffer. ImagingRawDecode calculates a packed-pixel row size, while the unpackers read separately padded bit planes. A caller can supply a buffer and image dimensions whose accepted size is smaller than the unpacker's actual footprint. This can disclose up to three adjacent heap bytes in output pixels or crash the process. This issue is fixed in version 13.0.0.
CVE-2026-112393 is a critical heap-based buffer overflow vulnerability in the Pillow library when saving TIFF images to in-memory destinations like io.BytesIO. The flaw occurs in the _tiffWriteProc function, which incorrectly reallocates memory based on the current buffer size rather than the write position, allowing writes past the allocated heap buffer. This can cause memory corruption and potential data leakage of heap contents. The vulnerability affects Pillow versions from 2.0.0 up to but not including 13.0.0 and was introduced in 2013. It can be triggered by processing attacker-controlled TIFF images with large out-of-line tags or embedded ICC profiles. The issue does not affect saving TIFF images to real files. A fix is available in Pillow 13.0.0.
A recursion depth check in the PdfParser.get_value() method of python-pillow's Pillow library is ineffective due to a default parameter value of -1 that never triggers the recursion limit guard. This allows crafted PDF files with deeply nested objects to cause a RecursionError when appending an image to an existing PDF using Image.save(..., format="PDF", append=True). The issue affects Pillow versions from 5.1.0 up to but not including 13.0.0 and is fixed in version 13.0.0.
CVE-2026-112390 is an infinite loop vulnerability in the python-pillow library's MIC image plugin. It occurs when processing a crafted Microsoft Image Composer (MIC) file containing an embedded TIFF with three or more image file directories (IFDs). The flaw causes the n_frames property to loop indefinitely at 100% CPU without raising exceptions or increasing memory usage. This affects Pillow versions from 7.2.0 up to but not including 13.0.0 when the optional olefile package is installed. The issue was introduced in April 2020 and fixed in version 13.0.0.
CVE-2026-111750 is a medium severity vulnerability in aiohttp, an asynchronous HTTP client/server framework for Python. Versions prior to 3.14.4 use a pure Python HTTP parser that accepts ambiguous HTTP request framing, allowing an unauthenticated attacker to perform HTTP request smuggling if the application runs without standard wheel extensions or with AIOHTTP_NO_EXTENSIONS enabled. This inconsistency in interpreting HTTP requests can lead to smuggling attacks. The issue is fixed in aiohttp version 3.14.4.
CVE-2026-111749 is a low-severity vulnerability in aiohttp prior to version 3.14.4 where a subdomain can remove the Host-Only scope from an existing parent-domain cookie. This can lead to host-only protections being stripped from cookies if a user accesses an untrusted subdomain. The impact is limited when applications do not reflect these cookies to browsers. The issue is fixed in aiohttp version 3.14.4.
CVE-2026-111748 is a vulnerability in aiohttp prior to version 3.14.4 where an attacker can send an absolute-form HTTP request that manipulates the Request.scheme property. This causes the application to use attacker-controlled scheme data rather than the actual connection protocol, potentially misleading security decisions based on the scheme. The issue is fixed in aiohttp version 3.14.4.
CVE-2026-111066 is a high-severity vulnerability in aiohttp, an asynchronous HTTP client/server framework for Python. Versions from 2.0.0 up to but not including 3.14.4 are affected. The flaw allows unauthenticated attackers to exhaust server file descriptors by sending specially crafted multipart requests to handlers using Request.post(). This uncontrolled resource consumption issue is fixed in version 3.14.4.
CVE-2026-111065 is a vulnerability in aiohttp, an asynchronous HTTP client/server framework for Python. Versions prior to 3.14.4 improperly handle Max-Age processing, which can overflow and prevent connections from closing properly. This can lead to temporary exhaustion of the connection pool until garbage collection reclaims the connections. The issue is fixed in version 3.14.4.
CVE-2026-111064 is a high-severity vulnerability in aiohttp, an asynchronous HTTP client/server framework for Python. Versions prior to 3.14.4 lack keepalive timeout handling during the initial phase of a request, allowing an attacker to keep idle connections open indefinitely without sending request data. This can exhaust server connection capacity. The issue is fixed in version 3.14.4.
AIOHTTP versions prior to 3.14.4 do not enforce the Secure attribute on shared cookies, allowing such cookies to be sent over unencrypted requests. This vulnerability is addressed in version 3.14.4.
**Affected:** `GitPython` **3.1.61** (latest release) and `main` — `git/objects/submodule/base.py`. `git diff 3.1.61 origin/main -- git/objects/submodule/` is empty, so both are identical here.
---
## The gap
The fix for `GHSA-hmq2-w58f-27jc` added `Submodule._validated_name()` and wired it into `update()` and five siblings, closing the `.gitmodules` **name** → `.git/modules/<name>` traversal. The other attacker-controlled `.gitmodules` field, **`path`**, is read raw:
```python
# git/objects/submodule/base.py:172-177
def _set_cache_(self, attr):
if attr in ("path", "_url", "_branch_path"):
reader = self.config_reader()
self.path = reader.get("path") # raw .gitmodules value
```
and GitPython's own containment guard is applied in only two of the places that consume it:
```
400: def _to_relative_path(cls, parent_repo, path) # the guard (abspath + commonpath containment)
542: path = cls._to_relative_path(repo, path) # add() — guarded
1041: module_checkout_path = self._to_relative_path(self.repo, module_path) # move() — guarded
```
`update()` validates only the name and then uses the path-derived absolute location directly:
```
788: self._validated_name(self.name) # NAME only
801: checkout_module_abspath = self.abspath # derived from self.path — unguarded
821: os.makedirs(checkout_module_abspath, exist_ok=True)
```
So `path = ../../../tmp/escaped` in an attacker-authored `.gitmodules` selects the directory that gets created and, on the clone path, populated from the submodule URL. The same absolute location is what `force_remove` hands to `shutil.rmtree`.
The asymmetry is the argument: this is not a missing concept — the project wrote `_to_relative_path()` precisely for this, and `add()`/`move()` use it. `update()` does not.
## Honest limits (please read before rating)
- **The most common flow is not affected.** `Repo.clone_from(...)` → `repo.submodules` → `sm.update(init=True)` re-derives `path` from a canonical tree lookup, and real git refuses to check out a tree containing a `..` component, so an evil `.gitmodules` never lands in the working tree in the first place. A reachable trigger therefore requires the victim's code to name a **non-HEAD commit** (a historical-commit API such as `submodule_update(previous_commit=...)`).
- **The researcher did not build that end-to-end trigger.** The researcher only verified first-hand the code above: the guard's two call sites, the name-only validation in `update()`, and the unguarded `abspath` → `os.makedirs()` flow at 3.1.61 == `main`.
## Suggested fix
Apply the guard the project already has, wherever the path is consumed:
```python
# in update(), before deriving abspath (and in any other consumer of self.path):
checkout_rel = self._to_relative_path(self.repo, self.path) # raises if it escapes the working tree
```
Better still, validate at the boundary: reject a `.gitmodules` entry whose `path` is absolute or contains a `..` component when the section is first read in `_set_cache_()`/`iter_items()`, so no consumer can be added later without the check. A regression test with `path = ../escaped` alongside the existing `name` test would pin both fields.
## Prior art checked
`GHSA-hmq2-w58f-27jc` (this is a residual of its fix, in the sibling field, not a re-report) plus the repository's 30 published advisories — none mentions the `path` field or `_to_relative_path`. Searched issues and PRs for `_to_relative_path`, `gitmodules path` and `submodule traversal`: no report of this.
## Credit
**kta1kri**.
---
## Appendix — `EVIDENCE_gitpython_path_unguarded_20260901.txt` (inlined; advisories accept no attachments)
```text
=== EVIDENCE: GitPython — the .gitmodules 'path' field reaches os.makedirs()/clone unguarded ===
Mon Aug 31 18:45:22 UTC 2026
--- artifact: tag 3.1.61 (latest release); git diff 3.1.61 origin/main -- git/objects/submodule/ is empty ---
--- the containment guard GitPython owns, and its only two call sites ---
33: _to_relative_path,
400: def _to_relative_path(cls, parent_repo: "Repo", path: PathLike) -> PathLike:
407: path = _to_relative_path(parent_repo.working_tree_dir, path)
542: path = cls._to_relative_path(repo, path)
1041: module_checkout_path = self._to_relative_path(self.repo, module_path)
--- the parent fix (_validated_name) call sites: it validates the NAME ---
309: def _validated_name(cls, name: str) -> str:
321: name = cls._validated_name(name)
541: cls._validated_name(name)
788: self._validated_name(self.name)
1040: self._validated_name(self.name)
1181: self._validated_name(self.name)
1439: self._validated_name(self.name)
1440: self._validated_name(new_name)
1489: self._validated_name(self.name)
--- update(): name validated, path not; abspath -> os.makedirs ---
try:
self._validated_name(self.name)
# ENSURE RE