{"record":{"id":"55324f72b311c017","repo":"apache/flink","slug":"expanding-entry-getname-would-create-entry-out","errorCode":null,"errorMessage":"expanding {entry.getName()} would create entry outside of {targetDir}","messagePattern":"expanding (.+?) would create entry outside of (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"critical","filePath":"flink-core/src/main/java/org/apache/flink/util/CompressionUtils.java","lineNumber":171,"sourceCode":"        try (InputStream fi = Files.newInputStream(Paths.get(inFilePath));\n                InputStream bi = new BufferedInputStream(fi);\n                final TarArchiveInputStream tai =\n                        new TarArchiveInputStream(\n                                gzipped ? new GzipCompressorInputStream(bi) : bi)) {\n            final File targetDir = new File(targetDirPath);\n            TarArchiveEntry entry;\n            while ((entry = tai.getNextTarEntry()) != null) {\n                unpackEntry(tai, entry, targetDir);\n            }\n        }\n    }\n\n    private static void unpackEntry(\n            TarArchiveInputStream tis, TarArchiveEntry entry, File targetDir) throws IOException {\n        String targetDirPath = targetDir.getCanonicalPath() + File.separator;\n        File outputFile = new File(targetDir, entry.getName());\n        if (!outputFile.getCanonicalPath().startsWith(targetDirPath)) {\n            throw new IOException(\n                    \"expanding \" + entry.getName() + \" would create entry outside of \" + targetDir);\n        }\n\n        if (entry.isDirectory()) {\n            if (!outputFile.mkdirs() && !outputFile.isDirectory()) {\n                throw new IOException(\"Failed to create directory \" + outputFile);\n            }\n\n            for (TarArchiveEntry e : entry.getDirectoryEntries()) {\n                unpackEntry(tis, e, outputFile);\n            }\n\n            return;\n        }\n\n        if (entry.isSymbolicLink()) {\n            // create symbolic link relative to tar parent dir\n            Files.createSymbolicLink(","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/util/CompressionUtils.java#L153-L189","documentation":"Zip-slip protection in the Java tar extraction path (unpackEntry): each entry's resolved canonical path must stay inside the target directory. Entries whose names escape via `../` or absolute paths are rejected before any file is written. This is a security guard against path traversal in malicious archives.","triggerScenarios":"Extracting a tar containing entries like `../../etc/passwd`, `/etc/something`, or symlinked traversal that resolves outside the extraction root, via extractTarFileUsingJava (non-Unix isUnix()=false path, i.e. Windows, or when the Java fallback is used).","commonSituations":"Downloading a user-supplied or third-party tar (UDF bundles, plugins) that contains crafted relative paths; archives produced by tools that emit entries with leading `../` segments; attempts to extract a deliberately malicious archive.","solutions":["Do not bypass the check — inspect the archive (`tar -tvf`) and identify the offending entry names","Rebuild the archive from trusted sources without `../` or absolute entry paths","Reject the input entirely if it comes from an untrusted source and fails this check"],"exampleFix":"// before: archive contains entry \"../../outside.txt\"\nCompressionUtils.extractTarFile(bundle, targetDir); // throws\n\n// after: sanitize at build time\ntar -cvf bundle.tar -C srcDir .   # entries relative, no '../' segments\nCompressionUtils.extractTarFile(bundle, targetDir);","handlingStrategy":"validation","validationCode":"try (TarArchiveInputStream t = new TarArchiveInputStream(new FileInputStream(f))) {\n    TarArchiveEntry e;\n    while ((e = t.getNextTarEntry()) != null) {\n        if (e.getName().startsWith(\"/\") || e.getName().contains(\"..\"))\n            throw new IOException(\"Refusing unsafe entry \" + e.getName());\n    }\n}","typeGuard":null,"tryCatchPattern":"catch (IOException) and reject the archive — never catch-and-continue for traversal errors; they indicate a hostile or broken input.","preventionTips":["Only extract archives from trusted, checksum-verified sources","Build archives with relative paths (`tar -C dir -cvf ...`) so entries can never traverse"],"tags":["flink-core","compression","security","zip-slip","path-traversal","tar"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}