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).

Ask Yourself Whether

Archives to expand are untrusted and:

There is a risk if you answered yes to any of those questions.

Recommended Secure Coding Practices

Sensitive Code Example

For tarfile module:

import tarfile

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

For zipfile module:

import zipfile

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

Compliant Solution

For tarfile module:

import tarfile

THRESHOLD_ENTRIES = 10000
THRESHOLD_SIZE = 1000000000
THRESHOLD_RATIO = 10

totalSizeArchive = 0;
totalEntryArchive = 0;

tfile = tarfile.open("TarBomb.tar")
for entry in tfile:
  tarinfo = tfile.extractfile(entry)

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

    ratio = sizeEntry / entry.size
    if ratio > THRESHOLD_RATIO:
      # ratio between compressed and uncompressed data is highly suspicious, looks like a Zip Bomb Attack
      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

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

tfile.close()

For zipfile module:

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()

See