Safeguard
Application Security

Zip Slip vulnerability cheat sheet

A concrete, question-driven cheat sheet on Zip Slip: how the archive-extraction path traversal bug works, real CVEs, and how to detect and fix it.

Priya Mehta
DevSecOps Engineer
8 min read

Zip Slip is a directory traversal vulnerability that lets a malicious archive — a ZIP, TAR, RAR, 7z, or WAR file — write files outside the folder your code intended to extract into. An attacker crafts an entry name like ../../../etc/cron.d/malicious or embeds a symlink that points outside the extraction root, and a vulnerable extraction routine writes wherever the entry says, not where the developer expected. Snyk's security research team disclosed the pattern on June 5, 2018, after finding it baked into archive-handling code across Java, JavaScript, .NET, Go, and Ruby libraries. It's not exotic: it's a missing path-normalization check in code most teams treat as boilerplate. Despite being seven years old, the same bug class resurfaced in npm's own tar package in 2021 (CVE-2021-32803, CVE-2021-32804), proving Zip Slip is a recurring implementation mistake, not a one-time patch. This cheat sheet covers how it works, which real CVEs it produced, and how to find and fix it in your codebase.

What is the Zip Slip vulnerability?

Zip Slip is a path traversal and arbitrary file write vulnerability that occurs when archive-extraction code trusts the file paths stored inside a compressed archive without validating that they resolve inside the intended output directory. Archive formats — ZIP, TAR, RAR, 7z, JAR, WAR — allow each entry to carry its own relative or absolute path. A well-behaved archive contains entries like images/logo.png. A malicious one contains an entry named ../../../../home/app/.ssh/authorized_keys or ..\..\..\Windows\System32\drivers\etc\hosts. If the extraction code simply concatenates the entry name onto the destination directory and writes the result, the .. sequences walk the write operation back up the directory tree and out of the sandboxed folder. Snyk coined the name "Zip Slip" in its 2018 disclosure because the write "slips" past the intended boundary. The same class of bug also applies to symbolic links planted inside an archive, which is the exact mechanism behind the 2021 node-tar advisories.

How does a Zip Slip attack actually work?

A Zip Slip attack works by abusing three variants of the same missing check: relative path traversal, absolute path overwrite, and symlink redirection. In the traversal variant, an attacker crafts an entry name containing repeated ../ sequences; vulnerable code does something equivalent to new File(outputDir, entry.getName()) without calling getCanonicalPath() and verifying the result still starts with outputDir, so the final write lands wherever the traversal sequence points. In the absolute-path variant, some libraries fail to detect that an entry name itself is a full path (e.g., /etc/passwd or C:\Windows\System32\...) and honor it directly, ignoring the destination directory entirely. In the symlink variant — the mechanism behind CVE-2021-32803 in node-tar — the archive first extracts a symlink, then extracts a regular file through that symlink, so the actual write target is controlled by the symlink rather than the file entry name. All three end the same way: an attacker who can get a target application to extract an untrusted archive can drop a file — a cron job, an SSH key, a .bashrc, a web shell in a served directory, or an overwritten binary — anywhere the extracting process has write permission.

Which CVEs and real-world libraries have been affected by Zip Slip?

Zip Slip has produced confirmed CVEs across at least five language ecosystems since 2018, and it resurfaced as recently as 2021 in one of the most widely used packages in the JavaScript ecosystem. Snyk's original research identified the flaw in more than 20 archive-handling libraries across Java, .NET, Go, JavaScript, and Ruby, assigning CVEs including CVE-2018-1002200 (DotNetZip, .NET) and CVE-2018-1002201 (mholt/archiver, Go). The bug wasn't limited to obscure packages — it reached widely-depended-on JAR, WAR, and archive-extraction utilities used inside build tools and CI pipelines, meaning a single vulnerable dependency could expose every downstream project that extracted an untrusted upload through it. The pattern proved durable: in August 2021, GitHub Security Lab and npm disclosed CVE-2021-32803 and CVE-2021-32804 in node-tar, the tar-extraction library used internally by the npm CLI itself, fixed in versions 6.1.2, 5.0.7, 4.4.15, and 3.2.3. Two related follow-up advisories, CVE-2021-37701 and CVE-2021-37712, patched additional Windows path-separator and race-condition bypasses in the same package weeks later. Because node-tar sits transitively under thousands of npm install chains, this single vulnerable dependency briefly gave attackers a file-write primitive on any CI runner or developer machine that installed an affected package that itself unpacked a crafted tarball.

How can you detect Zip Slip in your codebase?

You detect Zip Slip by auditing every place your code extracts an archive and checking whether it validates the resolved output path before writing. Search your codebase for extraction APIs — ZipInputStream, ZipFile, TarArchiveInputStream in Java; zipfile, tarfile.extractall() in Python; archiver, extract-zip, tar.extract() in Node.js; System.IO.Compression.ZipFile in .NET; archive/zip, archive/tar in Go — and trace what happens to entry.Name() or entry.getName() immediately after. The vulnerable pattern is any code that builds a destination path by joining the output directory with the raw entry name and never re-checks that the joined, canonicalized path still starts with the output directory. Static analysis tools (Semgrep, CodeQL, Snyk Code) ship rules specifically named "zip-slip" or "path-traversal-extraction" that flag this pattern automatically, and dependency scanners will flag known-vulnerable versions of node-tar (before 6.1.2), DotNetZip, or mholt/archiver if they appear in your SBOM. The harder part is scale: a mid-sized codebase can have archive-extraction logic in a dozen unrelated places — file upload handlers, plugin loaders, CI artifact unpacking, log-bundle importers — and each one needs the same check independently verified, which is why manual code review alone tends to miss instances that automated pattern matching catches.

How do you fix and prevent Zip Slip vulnerabilities?

You fix Zip Slip by canonicalizing every extracted path and rejecting any entry whose resolved path escapes the destination directory before a single byte is written. In Java, resolve the entry against the target directory, call .normalize() or .getCanonicalFile(), and verify the result's path starts with the destination directory's canonical path — reject and abort extraction otherwise; libraries like Apache Commons Compress and zt-zip added this check as their official 2018 patch. In Go, use filepath.Clean() on the joined path and confirm it has the destination directory as a prefix before calling os.Create(). In Node.js, use a maintained, patched version of tar (>=6.1.2) or extract-zip (>=2.0.0), both of which now enforce this check internally rather than trusting entry names. Beyond the extraction routine itself, three defense-in-depth controls matter: run extraction under a low-privilege, chrooted, or containerized process so even a successful traversal has nowhere useful to write; reject archive entries containing symlinks unless your application explicitly needs them; and pin and continuously scan archive-handling dependencies, since Zip Slip is a supply chain risk that travels with whichever library you npm install or pip install, not just code you wrote yourself.

Is Zip Slip still a risk in 2026?

Yes — Zip Slip remains a live risk because it's a pattern bug that gets reintroduced every time a developer writes new extraction code or a new archive library ships without the canonicalization check, not a single vulnerability that gets patched once and disappears. The eight-year gap between Snyk's original 2018 disclosure and the 2021 node-tar advisories shows the same mistake recurring in a completely different, actively maintained, widely-audited codebase. Any application that accepts user-uploaded ZIP/TAR/JAR files, unpacks third-party plugins, installs packages, or processes log bundles or backup archives is a candidate, and CI/CD pipelines that extract build artifacts or dependency tarballs are a particularly attractive target because a successful Zip Slip there can write directly into a runner's filesystem with build-level privileges. Treat every new archive-handling dependency you add — and every extraction routine you write — as a fresh instance of the same 2018 bug until proven otherwise.

How Safeguard Helps

Safeguard finds Zip Slip risk across both the code you write and the dependencies you pull in, then tells you which instances actually matter. Griffin AI scans extraction logic and dependency manifests to flag vulnerable archive-handling patterns and known-CVE library versions — including transitive packages like node-tar that most teams never audit directly — while reachability analysis determines whether the vulnerable extraction path is actually invoked with attacker-influenced input in your application, cutting through the noise of theoretical findings. Safeguard generates and ingests SBOMs so you have a continuously updated inventory of every archive library version in your supply chain, and where a fix is available, Safeguard opens an auto-fix pull request that bumps the dependency or patches the extraction routine directly, so remediation doesn't sit in a backlog waiting for a sprint.

Never miss an update

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