{"record":{"id":"d472d6812240532f","repo":"quarkusio/quarkus","slug":"bad-zip-entry-path","errorCode":null,"errorMessage":"Bad ZIP entry: ${path}","messagePattern":"Bad ZIP entry: (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/jbang/JBangDevModeLauncherImpl.java","lineNumber":75,"sourceCode":"            for (int i = 0; i < depCount; ++i) {\n                String name = contextStream.readUTF();\n                Path path = Paths.get(contextStream.readUTF());\n                deps.put(name, path);\n            }\n            Path projectRoot = Files.createTempDirectory(\"quarkus-jbang\");\n            try (OutputStream out = Files.newOutputStream(projectRoot.resolve(\"pom.xml\"))) {\n                out.write(pomContents.getBytes(StandardCharsets.UTF_8));\n            }\n            Path targetClasses = projectRoot.resolve(\"target/classes\");\n            Files.createDirectories(targetClasses);\n\n            try (ZipFile fz = new ZipFile(new File(jarFilePath))) {\n                Enumeration<? extends ZipEntry> entries = fz.entries();\n                while (entries.hasMoreElements()) {\n                    ZipEntry entry = entries.nextElement();\n                    Path path = targetClasses.resolve(entry.getName()).normalize();\n                    if (!path.startsWith(targetClasses)) {\n                        throw new IOException(\"Bad ZIP entry: \" + path);\n                    }\n                    if (entry.isDirectory()) {\n                        Files.createDirectories(path);\n                    } else {\n                        Files.createDirectories(path.getParent());\n                        Files.copy(fz.getInputStream(entry), path);\n                        Files.setLastModifiedTime(path, entry.getLastModifiedTime());\n                    }\n                }\n            }\n\n            Path srcDir = projectRoot.resolve(\"src/main/java\");\n            Files.createDirectories(srcDir);\n            Path source = Files.createSymbolicLink(srcDir.resolve(sourceFile.getFileName().toString()), sourceFile);\n            final LocalProject currentProject = LocalProject.loadWorkspace(projectRoot);\n            final ResolvedDependency appArtifact = ResolvedDependencyBuilder.newInstance()\n                    .setCoords(currentProject.getAppArtifact(ArtifactCoords.TYPE_JAR))\n                    .setResolvedPath(targetClasses)","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/independent-projects/bootstrap/core/src/main/java/io/quarkus/bootstrap/jbang/JBangDevModeLauncherImpl.java#L57-L93","documentation":"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).","triggerScenarios":"The jar being unpacked contains an entry whose name resolves outside targetClasses after normalization — e.g. absolute paths, '../' traversal, or entries with unexpected names.","commonSituations":"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.","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"],"exampleFix":"// before (jar entry: ../../evil.txt)\n// -> IOException Bad ZIP entry\n// after: rebuild jar with relative entry names\njar tf launcher.jar  # entries must be relative paths like com/foo/Bar.class","handlingStrategy":"validation","validationCode":"try (ZipFile zf = new ZipFile(new File(jarPath))) {\n    java.util.Enumeration<? extends ZipEntry> en = zf.entries();\n    Path target = Paths.get(targetClasses).toAbsolutePath().normalize();\n    while (en.hasMoreElements()) {\n        Path p = target.resolve(en.nextElement().getName()).normalize();\n        if (!p.startsWith(target)) throw new IllegalStateException(\"Unsafe ZIP entry in \" + jarPath);\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["jbang","zip","security","zip-slip"],"backgroundTag":"zip-slip-path-traversal","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}