langchain-ai/deepagents · critical · FleetImportError
{info.filename}: unsafe zip path
Error message
{info.filename}: unsafe zip path What it means
FleetImportError raised by `_validated_entries` (libs/talon/deepagents_talon/fleet_import.py:216) when an archive entry path is deemed unsafe — path traversal or absolute paths. `_normalized_zip_name` normalizes the entry, then `_is_unsafe_zip_path` rejects names that would escape the staging directory (e.g. '../', leading '/', drive letters). This is a zip-slip defense applied before any bytes are written.
Source
Thrown at libs/talon/deepagents_talon/fleet_import.py:216
lines.append("- Review .mcp.json.setup for requested tools and setup details.")
if result.interrupt_tools:
lines.append(
f"- Add HITL for sensitive tools with "
f"{INTERRUPT_ON_TOOLS_ENV_KEY}={','.join(result.interrupt_tools)}.",
)
return "\n".join(lines) + "\n"
def _validated_entries(archive: zipfile.ZipFile) -> dict[str, zipfile.ZipInfo]:
entries: dict[str, zipfile.ZipInfo] = {}
total_size = 0
for info in archive.infolist():
name = _normalized_zip_name(info.filename)
if name is None:
continue
if _is_unsafe_zip_path(name):
msg = f"{info.filename}: unsafe zip path"
raise FleetImportError(msg)
if _is_symlink(info):
msg = f"{name}: symlink entries are not supported"
raise FleetImportError(msg)
if info.is_dir():
continue
_validate_zip_entry_size(name, info)
if len(entries) >= _MAX_ZIP_ENTRY_COUNT:
msg = f"{archive.filename}: too many zip entries"
raise FleetImportError(msg)
total_size += info.file_size
if total_size > _MAX_ZIP_UNCOMPRESSED_BYTES:
msg = f"{archive.filename}: zip uncompressed size exceeds limit"
raise FleetImportError(msg)
entries[name] = info
return entries
def _normalized_zip_name(name: str) -> str | None:View on GitHub (pinned to a1af029e6e)
Solutions
- Rebuild the archive with relative, root-relative paths only (zip the directory contents, not absolute paths).
- Reject/inspect suspicious archives: `python -m zipfile -l fleet.zip` and remove entries starting with '/' or containing '..'.
- Only import fleet zips from trusted sources; the library intentionally refuses to sanitize unsafe paths.
Example fix
// before zip -r fleet.zip /home/user/.deepagents # entries like home/user/.deepagents/x or absolute // after cd /home/user/.deepagents && zip -r ../fleet.zip . # all entries relative to root
Defensive patterns
Strategy: validation
Validate before calling
import zipfile, posixpath
def archive_paths_are_safe(path) -> bool:
with zipfile.ZipFile(path) as z:
for name in z.namelist():
norm = posixpath.normpath(name.lstrip("/").replace("\\", "/"))
if norm.startswith("..") or posixpath.isabs(name):
return False
return True Try / catch
from deepagents_talon.fleet_import import import_fleet_zip, FleetImportError
try:
result = import_fleet_zip(source, target)
except FleetImportError as exc:
if "unsafe zip path" in str(exc):
raise SystemExit(f"{source} contains a path-traversal entry; do not import untrusted archives") from exc
raise Prevention
- Only import fleet zips from trusted sources.
- Build archives with relative paths rooted at the assistant home.
- Screen archives with a zip-slip checker before import; the library refuses rather than sanitizes.
When it happens
Trigger: Calling `import_fleet_zip` on an archive containing entries like '../evil.py', '/etc/passwd', or names that normalize outside the target. The original `info.filename` is included in the message.
Common situations: Archives crafted maliciously (zip-slip attack) or accidentally built with absolute paths (e.g. `zip -r fleet.zip /home/user/.deepagents` on some platforms); third-party fleet exports containing symlinks or traversal entries.
Related errors
- Path traversal not allowed
- Path traversal not allowed in glob pattern {pattern!r}
- Path traversal not allowed: {path}
- Path traversal detected after normalization: {path} -> {norm
- Path must start with one of {allowed_prefixes}: {path}
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/c38408e276313915.
Report an issue: GitHub.