apache/flink · critical · IOException
expanding {entry.getName()} would create entry outside of {t
Error message
expanding {entry.getName()} would create entry outside of {targetDir} What it means
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.
Source
Thrown at flink-core/src/main/java/org/apache/flink/util/CompressionUtils.java:171
try (InputStream fi = Files.newInputStream(Paths.get(inFilePath));
InputStream bi = new BufferedInputStream(fi);
final TarArchiveInputStream tai =
new TarArchiveInputStream(
gzipped ? new GzipCompressorInputStream(bi) : bi)) {
final File targetDir = new File(targetDirPath);
TarArchiveEntry entry;
while ((entry = tai.getNextTarEntry()) != null) {
unpackEntry(tai, entry, targetDir);
}
}
}
private static void unpackEntry(
TarArchiveInputStream tis, TarArchiveEntry entry, File targetDir) throws IOException {
String targetDirPath = targetDir.getCanonicalPath() + File.separator;
File outputFile = new File(targetDir, entry.getName());
if (!outputFile.getCanonicalPath().startsWith(targetDirPath)) {
throw new IOException(
"expanding " + entry.getName() + " would create entry outside of " + targetDir);
}
if (entry.isDirectory()) {
if (!outputFile.mkdirs() && !outputFile.isDirectory()) {
throw new IOException("Failed to create directory " + outputFile);
}
for (TarArchiveEntry e : entry.getDirectoryEntries()) {
unpackEntry(tis, e, outputFile);
}
return;
}
if (entry.isSymbolicLink()) {
// create symbolic link relative to tar parent dir
Files.createSymbolicLink(View on GitHub (pinned to 2f3c205e92)
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
Example fix
// before: archive contains entry "../../outside.txt" CompressionUtils.extractTarFile(bundle, targetDir); // throws // after: sanitize at build time tar -cvf bundle.tar -C srcDir . # entries relative, no '../' segments CompressionUtils.extractTarFile(bundle, targetDir);
Defensive patterns
Strategy: validation
Validate before calling
try (TarArchiveInputStream t = new TarArchiveInputStream(new FileInputStream(f))) {
TarArchiveEntry e;
while ((e = t.getNextTarEntry()) != null) {
if (e.getName().startsWith("/") || e.getName().contains(".."))
throw new IOException("Refusing unsafe entry " + e.getName());
}
} Try / catch
catch (IOException) and reject the archive — never catch-and-continue for traversal errors; they indicate a hostile or broken input.
Prevention
- Only extract archives from trusted, checksum-verified sources
- Build archives with relative paths (`tar -C dir -cvf ...`) so entries can never traverse
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Expand {entry.getName()} would create a file outside of {tar
- Mkdirs failed to create {targetDir}
- Interrupted when untarring file {inFilePath}
- Error untarring file {inFilePath}. Tar process exited with e
- Failed to create directory {outputFile}
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/55324f72b311c017.
Report an issue: GitHub.