apache/flink · error · IOException

Illegal escape from target directory

Error message

Illegal escape from target directory

What it means

FileUtils (unzip/expand of an archive into a target directory) is a Zip-Slip guard: for each ZipEntry it builds targetDirectory/entryName and verifies the result still starts with the target directory's path string. If an entry name like '../../etc/passwd' or an absolute path resolves outside the target, it throws IOException("Illegal escape from target directory") to prevent the archive from overwriting arbitrary files.

Source

Thrown at flink-core/src/main/java/org/apache/flink/util/FileUtils.java:537

     * @throws IOException if file open fails or in case of unsafe access outside target directory
     */
    public static Path expandDirectory(Path file, Path targetDirectory) throws IOException {
        FileSystem sourceFs = file.getFileSystem();
        FileSystem targetFs = targetDirectory.getFileSystem();
        Path rootDir = null;
        try (ZipInputStream zis = new ZipInputStream(sourceFs.open(file))) {
            ZipEntry entry;
            String targetDirStr = targetDirectory.toString();
            while ((entry = zis.getNextEntry()) != null) {
                Path relativePath = new Path(entry.getName());
                if (rootDir == null) {
                    // the first entry contains the name of the original directory that was zipped
                    rootDir = relativePath;
                }

                Path newFile = new Path(targetDirectory, relativePath);
                if (!newFile.toString().startsWith(targetDirStr)) {
                    throw new IOException("Illegal escape from target directory");
                }

                if (entry.isDirectory()) {
                    targetFs.mkdirs(newFile);
                } else {
                    try (FSDataOutputStream fileStream =
                            targetFs.create(newFile, FileSystem.WriteMode.NO_OVERWRITE)) {
                        // do not close the streams here as it prevents access to further zip
                        // entries
                        IOUtils.copyBytes(zis, fileStream, false);
                    }
                }
                zis.closeEntry();
            }
        }
        return new Path(targetDirectory, rootDir);
    }

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Inspect the archive with `unzip -l` or `jar tf` and look for entries starting with '/', '..' or drive letters; reject or re-create the archive
  2. Re-package the zip from a trusted source so all entry names are relative paths under the intended root
  3. If you control the producer, fix it to write entries with normalized relative names (no leading slash, no '..' segments)

Example fix

// producing safe entries when zipping
// before
zos.putNextEntry(new ZipEntry("/abs/or/../escaping/name"));
// after
zos.putNextEntry(new ZipEntry("rel/dir/name"));
Defensive patterns

Strategy: validation

Validate before calling

static void assertSafeEntries(Path zip) throws IOException {
    try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(zip))) {
        for (ZipEntry e; (e = zis.getNextEntry()) != null; ) {
            String n = e.getName();
            if (n.startsWith("/") || n.contains("..")) throw new IOException("Unsafe entry: " + n);
        }
    }
}

Try / catch

try { FileUtils.unzip(...) } catch (IOException e) { if (e.getMessage().contains("Illegal escape")) rejectArchive(); else throw e; }

Prevention

When it happens

Trigger: Unzipping a maliciously crafted or corrupted archive whose entry names contain '../' segments, rooted/absolute paths, or drive letters that make new Path(targetDirectory, relativePath) escape targetDirStr; can also fire on benign-but-odd archives where the string startsWith check fails for the normalized path.

Common situations: Deploying user-supplied job JARs/bundles or community distribution archives; downloading a partially-corrupted zip; a zip created by a tool that emits entries with leading '/' or Windows-style components.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/794fdb27229997c8. Report an issue: GitHub.