Compressed files need their own scan because an archive is a container: its contents are invisible until it is opened, can be nested and encrypted to stay that way, and can be crafted to expand into terabytes and crash the scanner. A safe scanner opens archives recursively under strict limits on depth, size and ratio, reports what it could not open, and treats an executable inside as the finding it is.

Why the archive is the attacker's favourite envelope

A zip file solves three problems for someone sending malware. It lets an executable or script pass through mail filters that block those types directly. It hides the real filename and extension from casual view until extraction. And it gives them levers, nesting and encryption, that make automated inspection harder without looking unusual, because ordinary people send zips all the time. Most of the disguised files described in disguised files and double extensions arrive inside an archive for exactly these reasons.

From the scanner's side, an archive is therefore not a file to be scanned but a set of files to be extracted, identified and scanned individually, then reassembled into a single verdict. Every format needs its own parser: zip, 7z, RAR, tar and gzip, CAB, ISO and IMG disk images, and the Office and Java formats that are zips underneath. A scanner that lacks a parser for a format cannot see inside it, which is why unusual archive formats are themselves a mild warning sign.

Nested archives

A zip inside a zip inside a zip is the simplest way to exhaust a lazy scanner. Each layer costs a decompression pass, and a scanner configured to look only one or two levels down passes the file as clean because it never reached the payload. The EICAR project distributes eicarcom2.zip, a test file nested two deep, for precisely this reason; if your gateway does not flag it, it is not opening nested archives. Real campaigns nest three or four levels, sometimes alternating formats (a RAR inside a zip inside an ISO) so that a scanner missing any one parser stops early.

The defence is a recursion limit that is high enough to reach realistic payloads and low enough to bound the work. ClamAV's default MaxRecursion is 17 levels, and it raises a Heuristics.Limits.Exceeded alert when the limit is hit if --alert-exceeds-max is set. Scan.now reports a deeply nested archive and does not pretend that "we stopped looking" means "nothing was there". A legitimate file is very rarely more than two archives deep.

Decompression bombs

42.zip

The famous example is 42.zip, which has circulated since around 2000. It is 42,374 bytes. Inside are sixteen zip files, each containing sixteen zip files, five layers deep, and at the bottom of each of the 1,048,576 branches sits a 4.3 GB file of repeated bytes. Fully extracted it comes to roughly 4.5 petabytes. A scanner or archive tool that extracts recursively without limits fills its disk, exhausts its memory or simply never finishes. The file contains no malware; the attack is the expansion itself, which is why a bomb is a denial-of-service against the scanner rather than an infection.

Non-recursive bombs

The DEFLATE algorithm used by zip caps at a compression ratio of roughly 1032 to 1, which is why 42.zip needed nesting. In 2019 David Fifield published a construction that overlaps files inside a single zip so that one compressed kernel is referenced by many entries, reaching a 5.5 GB expansion from 42 kilobytes and 281 TB from 10 MB in a single layer, with no recursion at all. It defeats scanners that only limited depth. Similar bombs exist for other formats: a gzip stream of zeros, a PNG whose decompressed pixel buffer is gigabytes, an XML document whose entities expand exponentially (the "billion laughs" attack), and a PDF whose streams inflate to fill memory.

How a scanner survives

LimitWhat it boundsClamAV option (default)
Recursion depthArchives inside archives--max-recursion (17)
Per-file sizeAny single extracted file--max-filesize (25 MB)
Total scan sizeSum of everything extracted from one upload--max-scansize (100 MB)
File countNumber of members across all layers--max-files (10000)
Compression ratioExpanded size divided by compressed sizeEnforced through the size limits above

The important design choice is what happens at the limit. Some scanners stop and return "clean", which turns every bomb into a free pass for whatever is hidden beneath it. The correct behaviour is to stop and report. Scan.now checks the declared uncompressed sizes in the archive's central directory before extracting anything, aborts when the ratio or total is implausible, and reports the file as a decompression bomb; the analysis runs in memory with hard ceilings so that an upload cannot affect other scans, and the file is never stored.

$ unzip -l 42.zip | tail -2
--------                     -------
   40960                     16 files   # 16 members, each itself a zip
$ zipinfo -t lib0.zip
16 files, 4294967296 bytes uncompressed, 4142 bytes compressed:  100.0%

Password-protected archives

Encrypting an archive with a password prevents any scanner from reading its members. Attackers have used this for years: the email says "the attached invoice is protected with password 2024" and the mail gateway, unable to look inside, lets it through. The pattern is easy to recognise because it makes no sense as security. A password sent alongside the file protects it from nobody except the scanner. Legitimate encrypted archives do exist, mostly between organisations exchanging sensitive data, and they send the password by a separate channel and to a recipient who expects it.

Scanners cannot decrypt, so they report. ClamAV raises Heuristics.Encrypted.Zip or Heuristics.Encrypted.RAR when run with --alert-encrypted; Scan.now reports a password-protected archive and, because the zip format leaves filenames unencrypted, still lists the member names and flags any that look executable. A password-protected zip whose only member is invoice.exe or document.lnk has told you everything you need to know without being opened.

Legacy zip encryption (ZipCrypto) is also weak enough to be broken with a known-plaintext attack, so it does not even protect the sender's data. Anyone who genuinely needs an encrypted archive should use 7z or zip with AES-256, and send the password separately.

What is inside matters more than the wrapper

Once opened, an archive is judged by its members, and the same rules apply as for loose files. An archive whose contents are an executable, a script, a shortcut or a disk image, however innocuous the archive's name, is reported as archive contains an executable. An archive with one member named like a document and typed like a program is a disguise. An archive containing an Office file with macros or a PDF with JavaScript inherits those findings. A scanner that reports "clean" for an archive should mean that every member was extracted, identified and passed, and Scan.now's file scanner reports per-member findings so that you can see which file inside triggered what.

The extraction tool is part of the attack surface

Two risks live in the archive tool rather than the archive's contents. Path traversal, often called Zip Slip, uses member names such as ../../../Users/you/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup/update.exe. An extractor that writes the name as given drops a file outside the destination folder, in this example into the Windows startup folder. Well-maintained tools now strip leading traversal, but libraries embedded in other software have repeatedly not. Parser bugs in the archive tool itself are the second risk: WinRAR shipped a path-traversal flaw in its ACE support for nineteen years (CVE-2018-20250) and in 2023 a bug (CVE-2023-38831) that ran a script when a user opened a harmless-looking file in an archive that contained a folder of the same name. Both were exploited in the wild. The defence is mundane: keep archive tools updated, prefer the operating system's built-in extractor for untrusted files, and extract into an empty folder so that anything that lands elsewhere is noticed.

Handling an untrusted archive

  1. List the contents before extracting: unzip -l, 7z l or the archive tool's preview. Names ending in an executable or script extension, names with ../, and a single member with a double extension are each a reason to stop.
  2. Scan the archive as a whole and read the per-member findings. If the scanner reports that it could not open something, that is a finding, not a pass.
  3. Do not enter a password that came with the file. If the archive is genuinely from someone you know, ask them for it through another channel and ask why it was needed.
  4. Extract into a new, empty folder with an updated tool, and treat the extracted files as new downloads: their origin is the same as the archive's.

The reasoning behind each step, and the checks that follow extraction, are laid out in is this file safe; how the pieces fit into a full scan is covered in how antivirus scanning works.