This rule is deprecated, and will eventually be removed.

Successful Zip Bomb attacks occur when an application expands untrusted archive files without controlling the size of the expanded data, which can lead to denial of service. A Zip bomb is usually a malicious archive file of a few kilobytes of compressed data but turned into gigabytes of uncompressed data. To achieve this extreme compression ratio, attackers will compress irrelevant data (eg: a long string of repeated bytes).

Why is this an issue?

Expanding archive files without controlling the size of the extracted data can lead to denial of service. A Zip bomb is a malicious archive of a few kilobytes of compressed data that expands into gigabytes of uncompressed data by compressing highly repetitive content. Applications that fail to validate the number of entries, total uncompressed size, or compression ratio of an archive are vulnerable to this attack.

What is the potential impact?

Denial of service

An attacker who can supply a malicious archive can exhaust the server’s disk space, memory, or CPU by triggering unbounded decompression. This can make the application completely unavailable to legitimate users and may require manual intervention to recover the affected system.

How to fix it in tarfile

Validate the number of entries and total uncompressed size when extracting archive files. Note that the tarfile module does not expose compressed entry sizes, so compression ratio checking is not applicable here.

Code examples

Noncompliant code example

import tarfile

tfile = tarfile.open("TarBomb.tar")
tfile.extractall('./tmp/')  # Noncompliant
tfile.close()

Compliant solution

import tarfile

THRESHOLD_ENTRIES = 10000
THRESHOLD_SIZE = 1000000000

totalSizeArchive = 0;
totalEntryArchive = 0;

tfile = tarfile.open("TarBomb.tar")
for entry in tfile:
  tarinfo = tfile.extractfile(entry)
  if tarinfo is None:
    continue  # skip directories, symlinks, etc.

  totalEntryArchive += 1
  sizeEntry = 0
  result = b''
  while True:
    sizeEntry += 1024
    totalSizeArchive += 1024

    if totalSizeArchive > THRESHOLD_SIZE:
      # the uncompressed data size is too much for the application resource capacity
      break

    chunk = tarinfo.read(1024)
    if not chunk:
      break

    result += chunk

  if totalEntryArchive > THRESHOLD_ENTRIES:
    # too much entries in this archive, can lead to inodes exhaustion of the system
    break

tfile.close()

How to fix it in zipfile

Validate the number of entries, total uncompressed size, and compression ratio when extracting archive files. Note that zfile.read() fully decompresses each entry into memory before the size check runs, since the zipfile module has no streaming per-entry extraction API. This pattern protects against entry-count attacks but cannot prevent a single malicious entry from causing an out-of-memory condition before the check fires.

Code examples

Noncompliant code example

import zipfile

zfile = zipfile.ZipFile('ZipBomb.zip', 'r')
zfile.extractall('./tmp/') # Noncompliant
zfile.close()

Compliant solution

import zipfile

THRESHOLD_ENTRIES = 10000
THRESHOLD_SIZE = 1000000000
THRESHOLD_RATIO = 10

totalSizeArchive = 0;
totalEntryArchive = 0;

zfile = zipfile.ZipFile('ZipBomb.zip', 'r')
for zinfo in zfile.infolist():
    print('File', zinfo.filename)
    data = zfile.read(zinfo)

    totalEntryArchive += 1

    totalSizeArchive = totalSizeArchive + len(data)
    ratio = len(data) / zinfo.compress_size
    if ratio > THRESHOLD_RATIO:
      # ratio between compressed and uncompressed data is highly suspicious, looks like a Zip Bomb Attack
      break

    if totalSizeArchive > THRESHOLD_SIZE:
      # the uncompressed data size is too much for the application resource capacity
      break

    if totalEntryArchive > THRESHOLD_ENTRIES:
      # too much entries in this archive, can lead to inodes exhaustion of the system
      break

zfile.close()

Resources

Articles & blog posts

Standards