Safeguard
Application Security•

CWE-409 Decompression Bombs: Handling Highly Compressed Data

A tiny ZIP or XML payload can expand into gigabytes. CWE-409 explains data amplification and the limits that stop it.

Safeguard Security Team
3 min read

CWE-409 is what happens when a product does not handle, or mishandles, compressed input with a very high compression ratio that produces a large output. MITRE gives the standard example: a decompression bomb, a small ZIP file that produces a large amount of data when decompressed.

Upload endpoints, archive importers, document converters and XML parsers are the usual places.

How it happens

The code reads a compressed stream and writes out whatever comes. It trusts the stream to be reasonable. Compression ratios of thousands to one are possible for repetitive data, so a file that looks harmless on disk can fill memory or disk when opened.

XML has its own version. MITRE lists an XML bomb in a web server module (CVE-2009-1955) and a parsing library that allowed an XML bomb (CVE-2003-1564). In these, nested entity definitions expand into far more text than the input suggests.

import zipfile

# Vulnerable: extracts everything with no size check
with zipfile.ZipFile("upload.zip") as z:
    z.extractall("/data/out")

What an attacker gains

Availability. The record notes that CPU and memory can be consumed quickly, leading to poor performance or a crash. No code execution is needed. One small upload can take a service down.

How to find it

The record lists no detection methods. Practical checks:

  • Find every place your code decompresses or expands untrusted data: ZIP, gzip, image formats, XML entities.
  • Test with a known high ratio test archive in a safe environment and watch memory and disk.
  • Check whether your XML parser has entity expansion limits turned on.

How to fix it

  1. Set a maximum total uncompressed size and a maximum ratio, and stop reading when either is exceeded.
  2. Read in chunks and count output bytes as you go, rather than trusting header fields.
  3. Limit the number of entries in an archive.
  4. Disable or cap XML entity expansion.
  5. Run decompression in a worker with memory and time limits.
import zipfile

MAX_TOTAL = 100 * 1024 * 1024  # 100 MB
total = 0
with zipfile.ZipFile("upload.zip") as z:
    for info in z.infolist():
        total += info.file_size
        if total > MAX_TOTAL:
            raise ValueError("archive too large when expanded")
    z.extractall("/data/out")

The header size can be forged in some formats, so for hostile input also count bytes while streaming.

Quick check

Why not just limit upload size?

Upload size measures the compressed bytes. The damage comes from the expanded size, so that is what you must limit.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.