Coordinated Disclosure Timeline
- 2023-10-30: Initial contact with Treasure Data in request for a Security contact.
- 2023-12-06: Vulnerability was reported via GitHub’s private vulnerability reporting feature after it was enabled by the maintainers.
- 2024-01-19: Vulnerability was fixed in a temporary private fork.
- 2024-02-07: Maintainer has requested to postpone the advisory to a later date.
- 2024-02-13: Fixed version of Digdag was released with v0.10.5.1.
- 2024-02-14: Security advisory was published by the maintainers of Digdag.
Summary
Treasure Data’s digdag workload automation system is susceptible to a path traversal vulnerability if it’s configured to store log files locally.
Project
digdag
Tested Version
Details
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
:
@GET
@Produces("application/gzip")
@Path("/api/logs/{attempt_id}/files/{file_name}")
@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()),
getAuthenticatedUser()));
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:
@Override
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.
Impact
This issue may lead to Information Disclosure.
CVE
- CVE-2024-25125
Credit
This issue was discovered and reported by GHSL team member @p- (Peter Stöckli).
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2023-221
in any communication regarding this issue.