MCPSafe.io
RegistryThreatsMethodologyDocsPricingScanSign in
MCPSafe.io

Security checks for MCP servers — public packages and private repos, fast or deep.

Legal

Privacy PolicyCookie PolicyTerms of ServiceSecurity disclosure

Resources

State of MCP SecuritySupportSystem statusMade in Germany 🇩🇪

© 2026 MCPSafe. All rights reserved.

GDPR — Privacy Policy
← Threat Catalog

Server Implementation

Archive traversal (zip-slip)

HIGHAIVSS 7.5CWE: CWE-22OWASP: LLM02Agentic: T03Rule: MCP-081

A tool extracts a user-supplied archive (.zip, .tar, .tar.gz) without validating member paths, so an entry like `../../etc/cron.d/foo` overwrites files outside the target directory.

What it is

Zip-slip is path traversal through an archive. Both ZIP and TAR allow file entries with arbitrary relative paths, and most language stdlibs happily write `../../../etc/passwd` to disk if that is what the archive says. `tarfile.extractall(path)` and `ZipFile.extractall(path)` in Python — and their Node/Java equivalents — were famously vulnerable for years and are still the default way to unpack an archive.

Why it matters for MCP

MCP servers that accept document uploads, package manifests, or code bundles routinely extract archives. An LLM prompted to process a user-provided file will forward whatever bytes were supplied; a malicious archive retrieved from the web can replace server code or secrets while the tool believes it extracted a harmless zip.

Vulnerable example

example.py
1
import tarfile
2
3
@server.tool()
4
def extract_bundle(path: str, dest: str) -> int:
5
    # Malicious members with "../" escape `dest`.
6
    with tarfile.open(path) as tar:
7
        tar.extractall(dest)
8
        return len(tar.getnames())

Secure example

example.py
1
import tarfile
2
from pathlib import Path
3
4
def _safe_members(tar, dest: Path):
5
    dest = dest.resolve()
6
    for member in tar.getmembers():
7
        target = (dest / member.name).resolve()
8
        if not str(target).startswith(str(dest) + "/") and target != dest:
9
            raise ValueError(f"unsafe path in archive: {member.name}")
10
        yield member
11
12
@server.tool()
13
def extract_bundle(path: str, dest: str) -> int:
14
    dest_path = Path(dest)
15
    with tarfile.open(path) as tar:
16
        members = list(_safe_members(tar, dest_path))
17
        tar.extractall(dest_path, members=members)
18
        return len(members)

How MCPSafe detects this

We flag `tarfile.extractall` and `ZipFile.extractall` calls with no `members=` / per-member path validation, plus Node `unzipper.Extract`, `tar.extract`, and `decompress()` without a path-filter callback.

See the full threat catalog for every documented detection.

Framework alignment

OWASP LLM Top-10 (2025)
LLM02 — Sensitive Information Disclosure
OWASP Agentic AI Top-10
T03 — Privilege Compromise
AIVSS v0.5
7.5 (HIGH)AIVSS:1.0/S:HIGH/AV:N/AU:L/BR:H/CD:D

Illustrative CVEs

CVEs of the same CWE class. Not MCP-specific, but exemplify the failure mode MCPSafe detects.

  • CVE-2018-1002200 — plexus-archiver zip-slip — the canonical CVE for this class
  • CVE-2023-4863 — (adjacent) archive-handling vulnerability in libwebp

Further reading

  • CWE-22: Improper Limitation of a Pathname ('Path Traversal')
  • Snyk: Zip-slip vulnerability

Scan an MCP server for this issue

MCPSafe runs this check — and every other rule in the catalog — on any MCP server you paste in.

Scan now