apache/beam · error · IOException
Cannot unzip file containing an entry with ".." in the…
Error message
Cannot unzip file containing an entry with ".." in the name:
What it means
ZipFiles.checkName guards against zip-slip path traversal: an entry whose name contains a '..' path element could escape targetDirectory when extracted. unzipFile rejects the whole archive with this IOException naming the offending entry.
Solutions
- Inspect and sanitize the zip: reject or rewrite entries containing '..' components before extraction
- Use a safe unzip helper that canonicalizes paths and validates they stay under targetDirectory
- Only unzip archives from trusted sources
- Quarantine the offending archive and alert on the attempt if it came from an untrusted uploader
Example fix
// before
ZipFiles.unzipFile(untrustedZip, target);
// after
try (ZipFile zf = new ZipFile(untrustedZip)) {
for (ZipEntry e : Collections.list(zf.entries())) {
if (Arrays.asList(new File(e.getName()).getPath().split("[\\/]")).contains("..")) {
throw new IOException("unsafe entry: " + e.getName());
}
}
}
ZipFiles.unzipFile(untrustedZip, target); Defensive patterns
Strategy: validation
Validate before calling
boolean hasUnsafeEntry(Path zip) throws IOException {
try (ZipFile zf = new ZipFile(zip.toFile())) {
return Collections.list(zf.entries()).stream().map(ZipEntry::getName)
.anyMatch(n -> Arrays.asList(new File(n).getPath().split("[\\/]")).contains(".."));
}
} Try / catch
try {
ZipFiles.unzipFile(zip, targetDir);
} catch (IOException e) {
if (e.getMessage().contains("..\" in the name")) {
// reject the archive as malicious/invalid
throw new SecurityException("zip-slip attempt", e);
}
throw e;
} Prevention
- Never unzip untrusted archives without pre-scanning entry names
- Canonicalize target paths and verify containment after any unzip
- Log and quarantine archives that trigger traversal checks
When it happens
Trigger: Calling ZipFiles.unzipFile on a zip that contains an entry name with a literal '..' path component (e.g. '../../etc/passwd'), as opposed to harmless names like 'foo..bar'.
Common situations: Extracting untrusted zips downloaded from users or third parties; processing zips crafted for path-traversal attacks; CI jobs unpacking unvetted artifacts.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- Builder method has to be explicitly allowed
- Builder method name has to be explicitly allowed
- cannot register Coder : method named 'of' with arguments…
- Constructor method needs to be explicitly allowed
- error validating file path
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/ea7e0f12c7afc6df.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/util/ZipFiles.java:162
/**
* Checks that the given entry name is legal for unzipping: if it contains ".." as a name element,
* it could cause the entry to be unzipped outside the directory we're unzipping to.
*
* @throws IOException if the name is illegal
*/
private static void checkName(String name) throws IOException {
// First just check whether the entry name string contains "..".
// This should weed out the vast majority of entries, which will not
// contain "..".
if (name.contains("..")) {
// If the string does contain "..", break it down into its actual name
// elements to ensure it actually contains ".." as a name, not just a
// name like "foo..bar" or even "foo..", which should be fine.
File file = new File(name);
while (file != null) {
if ("..".equals(file.getName())) {
throw new IOException(
"Cannot unzip file containing an entry with " + "\"..\" in the name: " + name);
}
file = file.getParentFile();
}
}
}
/**
* Zips an entire directory specified by the path.
*
* @param sourceDirectory the directory to read from. This directory and all subdirectories will
* be added to the zip-file. The path within the zip file is relative to the directory given
* as parameter, not absolute.
* @param zipFile the zip-file to write to.
* @throws IOException the zipping failed, e.g. because the input was not readable.
* @throws IllegalArgumentException sourceDirectory is not a directory, or zipFile already exists.
*/
public static void zipDirectory(File sourceDirectory, File zipFile) throws IOException {View on GitHub (pinned to 12126d8942)