alibaba/arthas · error · IOException
Bad zip entry: {currentEntry}
Error message
Bad zip entry: {currentEntry} What it means
IOUtils.ungzip/unzip routine extracts each ZipEntry under a base directory newPath. Before writing, it checks isSubFile(newPath, destFile) — a path-traversal (zip-slip) guard ensuring the resolved destination stays inside newPath. If an entry resolves outside the base (e.g. ../ escapes or absolute paths), it throws IOException("Bad zip entry: <currentEntry>").
Source
Thrown at common/src/main/java/com/taobao/arthas/common/IOUtils.java:125
ZipFile zip = null;
try {
int BUFFER = 1024 * 8;
zip = new ZipFile(file);
File newPath = new File(extractFolder);
newPath.mkdirs();
Enumeration<? extends ZipEntry> zipFileEntries = zip.entries();
// Process each entry
while (zipFileEntries.hasMoreElements()) {
// grab a zip file entry
ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
String currentEntry = entry.getName();
File destFile = new File(newPath, currentEntry);
if (!isSubFile(newPath, destFile)) {
throw new IOException("Bad zip entry: " + currentEntry);
}
// destFile = new File(newPath, destFile.getName());
File destinationParent = destFile.getParentFile();
// create the parent directory structure if needed
destinationParent.mkdirs();
if (!entry.isDirectory()) {
BufferedInputStream is = null;
BufferedOutputStream dest = null;
try {
is = new BufferedInputStream(zip.getInputStream(entry));
int currentByte;
// establish buffer for writing file
byte data[] = new byte[BUFFER];
// write the current file to diskView on GitHub (pinned to 21cf2e9ba5)
Solutions
- Only extract archives from trusted, checksum-verified sources.
- If you control packaging, ensure entry names are relative with no '..' segments.
- Catch IOException and abort the extraction, deleting partial output.
- Run extraction in a sandboxed/throwaway directory so escapes are contained.
Example fix
// before - blindly trust upstream archive
IOUtils.unzip(downloadedZip, targetDir); // entry '../evil' -> throws Bad zip entry
// after - verify source + isolate
if (!checksumMatches(downloadedZip)) throw new IOException("untrusted archive");
File sandbox = Files.createTempDirectory("unzip").toFile();
try {
IOUtils.unzip(downloadedZip, sandbox);
} catch (IOException e) {
FileUtils.deleteQuietly(sandbox);
throw e;
} Defensive patterns
Strategy: validation
Validate before calling
File base = newPath.getCanonicalFile();
for (ZipEntry e : Collections.list(zip.entries())) {
File dest = new File(newPath, e.getName()).getCanonicalFile();
if (!dest.toPath().startsWith(base.toPath())) {
throw new IOException("refusing zip-slip entry: " + e.getName());
}
} Type guard
static boolean allEntriesInside(ZipFile zip, File base) throws IOException {
Path bp = base.getCanonicalFile().toPath();
Enumeration<? extends ZipEntry> en = zip.entries();
while (en.hasMoreElements()) {
Path dp = new File(base, en.nextElement().getName()).getCanonicalFile().toPath();
if (!dp.startsWith(bp)) return false;
}
return true;
} Try / catch
try {
IOUtils.unzip(zip, targetDir);
} catch (IOException e) {
if (e.getMessage().startsWith("Bad zip entry")) {
FileUtils.deleteQuietly(targetDir); // discard partial extraction
throw new SecurityException("rejected malicious archive", e);
}
throw e;
} Prevention
- Extract only verified archives from trusted sources (checksum/signature).
- Extract into a throwaway sandbox directory and move validated contents out.
- Inspect entry names for '..' or absolute paths before extracting.
- Catch the IOException and purge partial output to avoid leaving attacker-controlled files.
When it happens
Trigger: Extracting a maliciously or accidentally crafted archive whose entry names contain '..' segments or absolute paths that would escape the target directory (classic zip-slip).
Common situations: Downloading an Arthas distribution/archive from an untrusted or tampered source; a re-packaged archive with entry names like ../../etc/passwd; an archiver that emitted absolute entry names.
Related errors
- File '{file}' exists but is a directory
- File '{file}' cannot be written to
- Directory '{parent}' could not be created
- Failed to prepare MCP upload directory
- Failed to create MCP upload directory
AI-assisted analysis of alibaba/arthas@21cf2e9ba5 (2026-08-14).
Data as JSON: /api/errors/c7745ea48385393c.
Report an issue: GitHub.