quarkusio/quarkus · error · IOException
Bad ZIP entry: ${path}
Error message
Bad ZIP entry: ${path} What it means
JBangDevModeLauncherImpl.main() extracts the launcher jar's entries into a target classes directory. For each ZIP entry it normalizes the resolved path and rejects any entry that escapes the target directory (zip-slip protection) with IOException("Bad ZIP entry: " + path).
Source
Thrown at independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/jbang/JBangDevModeLauncherImpl.java:75
for (int i = 0; i < depCount; ++i) {
String name = contextStream.readUTF();
Path path = Paths.get(contextStream.readUTF());
deps.put(name, path);
}
Path projectRoot = Files.createTempDirectory("quarkus-jbang");
try (OutputStream out = Files.newOutputStream(projectRoot.resolve("pom.xml"))) {
out.write(pomContents.getBytes(StandardCharsets.UTF_8));
}
Path targetClasses = projectRoot.resolve("target/classes");
Files.createDirectories(targetClasses);
try (ZipFile fz = new ZipFile(new File(jarFilePath))) {
Enumeration<? extends ZipEntry> entries = fz.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
Path path = targetClasses.resolve(entry.getName()).normalize();
if (!path.startsWith(targetClasses)) {
throw new IOException("Bad ZIP entry: " + path);
}
if (entry.isDirectory()) {
Files.createDirectories(path);
} else {
Files.createDirectories(path.getParent());
Files.copy(fz.getInputStream(entry), path);
Files.setLastModifiedTime(path, entry.getLastModifiedTime());
}
}
}
Path srcDir = projectRoot.resolve("src/main/java");
Files.createDirectories(srcDir);
Path source = Files.createSymbolicLink(srcDir.resolve(sourceFile.getFileName().toString()), sourceFile);
final LocalProject currentProject = LocalProject.loadWorkspace(projectRoot);
final ResolvedDependency appArtifact = ResolvedDependencyBuilder.newInstance()
.setCoords(currentProject.getAppArtifact(ArtifactCoords.TYPE_JAR))
.setResolvedPath(targetClasses)View on GitHub (pinned to e1c734241f)
Solutions
- Verify the jar's integrity and rebuild it (jar tf; 'mvn clean install') — a legit jar should never contain traversal entries
- Check the jar's entry names for absolute paths or '../' segments and fix the process that produced it
- Re-download/re-obtain the jar if it came from an external source and may be tampered
- Ensure you are unpacking the intended launcher jar, not another file
Example fix
// before (jar entry: ../../evil.txt) // -> IOException Bad ZIP entry // after: rebuild jar with relative entry names jar tf launcher.jar # entries must be relative paths like com/foo/Bar.class
Defensive patterns
Strategy: validation
Validate before calling
try (ZipFile zf = new ZipFile(new File(jarPath))) {
java.util.Enumeration<? extends ZipEntry> en = zf.entries();
Path target = Paths.get(targetClasses).toAbsolutePath().normalize();
while (en.hasMoreElements()) {
Path p = target.resolve(en.nextElement().getName()).normalize();
if (!p.startsWith(target)) throw new IllegalStateException("Unsafe ZIP entry in " + jarPath);
}
} Prevention
- Verify jar integrity before unpacking (jar tf)
- Reject jars containing absolute paths or ../ entries
- Obtain launcher jars from trusted sources and rebuild locally when in doubt
When it happens
Trigger: The jar being unpacked contains an entry whose name resolves outside targetClasses after normalization — e.g. absolute paths, '../' traversal, or entries with unexpected names.
Common situations: Tampered or malformed jar; jar built on a different platform with odd entry names; entries containing drive letters or leading slashes; corrupted jar produced by a broken build process.
Related errors
- Bad ZIP entry: ${target}
- No producers for required item %s, step builder used: %s
- cycle detection failure report (dynamic CycleBuildException
- Build step '%s' does not produce any build item and thus wil
- Cannot consume/produce interface or abstract class build ite
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/d472d6812240532f.
Report an issue: GitHub.