skip to content
Back to
Home Bounties Research Advisories CodeQL Wall of Fame Get Involved Events
March 1, 2024

GHSL-2023-221: Path traversal vulnerability in digdag - CVE-2024-25125

Peter Stöckli

Coordinated Disclosure Timeline


Treasure Data’s digdag workload automation system is susceptible to a path traversal vulnerability if it’s configured to store log files locally.



Tested Version



Absolute Path Traversal (GHSL-2023-221)

Treasure Data’s digdag workload automation system was susceptible to a path traversal vulnerability if it’s configured to store log files locally. The problem stems from the fact that the filename param from the API method getFile:

@ApiOperation("Download a log file")
public byte[] getFile(
        @ApiParam(value="attempt id", required=true)
        @PathParam("attempt_id") long attemptId,
        @ApiParam(value="log file name", required=true)
        @PathParam("file_name") String fileName)

flows into the getFile method of the configurable logserver instance (after performing access and sanity checks):

return tm.<byte[], ResourceNotFoundException, IOException, StorageFileNotFoundException, AccessControlException>begin(() -> {
    final LogFilePrefix prefix = getPrefix(attemptId, // NotFound, AccessControl
            (p, a) -> ac.checkGetLogFiles(
                    WorkflowTarget.of(getSiteId(), a.getSession().getWorkflowName(), p.getName()),
    return logServer.getFile(prefix, fileName);
}, ResourceNotFoundException.class, IOException.class, StorageFileNotFoundException.class, AccessControlException.class);

If digdag is configured to store log files locally (e.g. whens started with the --task-log command line argument). A LocalFileLogServerFactory instance is used. The LocalFileLogServerFactory class defines getFile as follows:

protected byte[] getFile(String dateDir, String attemptDir, String fileName)
    throws StorageFileNotFoundException
    Path path = getPrefixDir(dateDir, attemptDir).resolve(fileName);
    try (InputStream in = Files.newInputStream(path)) {
        return ByteStreams.toByteArray(in);

Since the user-controlled fileName parameter flows largely unchecked into the resolve method of java.nio.file.Path an absolute path can be provided to the web application in an URL-encoded form such as %2fetc%2fpasswd. This method circumvents typical servlet filters that look for .. and similar in URLs.

The resolve(Path other) and resolve(String other) methods of java.nio.file.Path ignore the original path if other is an absolute Path.

This vulnerability was discovered with the help of CodeQL’s Uncontrolled data used in path expression query.


This issue may lead to Information Disclosure.



This issue was discovered and reported by GHSL team member @p- (Peter Stöckli).


You can contact the GHSL team at, please include a reference to GHSL-2023-221 in any communication regarding this issue.