apache/cassandra · error · IllegalArgumentException

Illegal file to fetch:

Error message

Illegal file to fetch: 

What it means

AsyncProfilerService.fetch reads a previously generated profiling result file from the profiles log directory. To prevent path traversal it resolves the requested file and requires that its absolute parent equals the log directory; anything escaping that directory (e.g. '../secrets') is rejected with this IllegalArgumentException.

Source

Thrown at src/java/org/apache/cassandra/service/AsyncProfilerService.java:349

        try
        {
            maybeCreateProfilesLogDir();
            return Arrays.stream(new File(logDir).list()).map(File::name).sorted().collect(toList());
        }
        catch (Throwable t)
        {
            return List.of();
        }
    }

    @Override
    public byte[] fetch(String resultFile) throws IOException
    {
        try
        {
            if (!Path.of(logDir, resultFile).toAbsolutePath().getParent().equals(Path.of(logDir)))
            {
                throw new IllegalArgumentException("Illegal file to fetch: " + resultFile);
            }
            maybeCreateProfilesLogDir();
            return Files.readAllBytes(new File(logDir, resultFile).toPath());
        }
        catch (NoSuchFileException t)
        {
            logger.error("Result file " + resultFile + " not found or error occurred while returning it.", t);
            throw t;
        }
    }

    @Override
    public void purge()
    {
        maybeCreateProfilesLogDir();
        new File(logDir).deleteRecursive();
    }

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Pass only the plain file name as returned by the list() operation, with no slashes or '..' segments
  2. List available results via the list() MBean operation and pick a name from it
  3. Verify Path.of(logDir, name).toAbsolutePath().getParent() equals the log dir before calling

Example fix

// before
byte[] data = service.fetch("../heap.dump");
// after
String name = (String) service.list().stream().filter(f -> f.endsWith(".html")).findFirst().get();
byte[] data = service.fetch(name);
Defensive patterns

Strategy: validation

Validate before calling

Path expected = Path.of(logDir).toAbsolutePath();
Path resolved = Path.of(logDir, name).toAbsolutePath();
if (!expected.equals(resolved.getParent())) throw new IllegalArgumentException("file must be a bare name inside the log dir");

Try / catch

try { return svc.fetch(name); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("Illegal file to fetch")) return null; throw e; }

Prevention

When it happens

Trigger: Calling fetch("somefile") where the resolved path's parent is not the profiles log dir — e.g. fetch("../cassandra.yaml"), absolute paths, or names containing path separators.

Common situations: Tooling concatenating user input into the file name; attempting to download non-profile files through the profiling MBean; passing names produced by a different Cassandra version with different log dir layout.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/04581d7e593ad9ea. Report an issue: GitHub.