GoogleContainerTools/jib · critical · IOException
Blocked unzipping files outside destination: ${entryName} fr
Error message
Blocked unzipping files outside destination: ${entryName} from ${archive} What it means
ZipUtil.unzip guards against zip-slip path traversal: each entry's resolved canonical path must remain under the destination's canonical path. When an entry name escapes the destination (e.g. via ../ segments or absolute entry names), unzip throws IOException 'Blocked unzipping files outside destination: <entryName> from <archive>'.
Source
Thrown at jib-plugins-common/src/main/java/com/google/cloud/tools/jib/plugins/common/ZipUtil.java:80
throws IOException {
if (enableReproducibleTimestamps
&& Files.isDirectory(destination)
&& destination.toFile().list().length != 0) {
throw new IllegalStateException(
"Cannot enable reproducible timestamps. They can only be enabled when the target root doesn't exist or is an empty directory");
}
String canonicalDestination = destination.toFile().getCanonicalPath();
List<ZipEntry> entries = new ArrayList<>();
try (InputStream fileIn = new BufferedInputStream(Files.newInputStream(archive));
ZipInputStream zipIn = new ZipInputStream(fileIn)) {
for (ZipEntry entry = zipIn.getNextEntry(); entry != null; entry = zipIn.getNextEntry()) {
entries.add(entry);
Path entryPath = destination.resolve(entry.getName());
String canonicalTarget = entryPath.toFile().getCanonicalPath();
if (!canonicalTarget.startsWith(canonicalDestination + File.separator)) {
String offender = entry.getName() + " from " + archive;
throw new IOException("Blocked unzipping files outside destination: " + offender);
}
if (entry.isDirectory()) {
Files.createDirectories(entryPath);
} else {
if (entryPath.getParent() != null) {
Files.createDirectories(entryPath.getParent());
}
try (OutputStream out = new BufferedOutputStream(Files.newOutputStream(entryPath))) {
ByteStreams.copy(zipIn, out);
}
}
}
}
preserveModificationTimes(destination, entries, enableReproducibleTimestamps);
}
/**View on GitHub (pinned to fb949e2676)
Solutions
- Inspect the offending archive: the entry name after 'Blocked unzipping files outside destination:' identifies the malicious entry — replace the archive with a trusted copy.
- Re-download or rebuild the archive from a trusted source (verify checksums) since legitimate JARs should not contain traversal entries.
- Sanitize entry names before creating archives you control, ensuring they are relative and contain no '..' segments.
Example fix
// before (creating an archive)
ZipEntry entry = new ZipEntry("../outside.txt");
// after
ZipEntry entry = new ZipEntry("safe/relative/outside.txt"); Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-scan archive entries for traversal before unzipping
try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(archive))) {
ZipEntry e;
while ((e = zis.getNextEntry()) != null) {
Path resolved = destination.resolve(e.getName()).normalize();
if (!resolved.startsWith(destination.normalize())) {
throw new IOException("unsafe zip entry: " + e.getName());
}
}
} Try / catch
try {
ZipUtil.unzip(archive, destination, enableRepro);
} catch (IOException e) {
if (e.getMessage().startsWith("Blocked unzipping files outside destination")) {
logger.error("Zip-slip blocked; the archive is untrusted: " + e.getMessage());
} else {
throw e;
}
} Prevention
- Treat this error as a sign of a malicious/corrupt archive — replace the source
- Verify archive checksums/signatures before extraction
- Never disable or bypass the zip-slip check
When it happens
Trigger: unzip processes a ZipEntry whose getName() contains '..' segments or an absolute path so that destination.resolve(entry.getName()).getCanonicalPath() does not start with canonicalDestination + File.separator.
Common situations: Extracting a maliciously or accidentally crafted archive whose entries contain '../../etc/passwd' style names; archives built on Windows with absolute entry names; build caches poisoned with tampered dependency archives.
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
- Blocked unzipping files outside destination: ${offender}
- Cannot enable reproducible timestamps. They can only be enab
- SHA-256 algorithm implementation not found - might be a brok
- SHA-256 algorithm produced invalid hash: + ex.getMessage()
- platform configuration is missing an OS value
AI-assisted analysis of GoogleContainerTools/jib@fb949e2676 (2026-09-06).
Data as JSON: /api/errors/e13b6a6e210ac849.
Report an issue: GitHub.