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

  1. Verify the jar's integrity and rebuild it (jar tf; 'mvn clean install') — a legit jar should never contain traversal entries
  2. Check the jar's entry names for absolute paths or '../' segments and fix the process that produced it
  3. Re-download/re-obtain the jar if it came from an external source and may be tampered
  4. 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

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


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/d472d6812240532f. Report an issue: GitHub.