Skip to content

Commit eae89b0

Browse files
authored
Merge pull request from GHSA-5mp4-32rr-v3x5
Fix path traversal vulnerability in LocalFileLogServer
2 parents 323fa19 + 5326502 commit eae89b0

File tree

3 files changed

+41
-2
lines changed

3 files changed

+41
-2
lines changed

digdag-core/src/main/java/io/digdag/core/log/LocalFileLogServerFactory.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.digdag.core.log;
22

3+
import java.nio.file.NoSuchFileException;
34
import java.util.concurrent.locks.ReentrantReadWriteLock;
45
import java.io.InputStream;
56
import java.io.OutputStream;
@@ -122,11 +123,15 @@ protected void listFiles(String dateDir, String attemptDir, boolean enableDirect
122123
protected byte[] getFile(String dateDir, String attemptDir, String fileName)
123124
throws StorageFileNotFoundException
124125
{
125-
Path path = getPrefixDir(dateDir, attemptDir).resolve(fileName);
126+
Path prefixDir = getPrefixDir(dateDir, attemptDir);
127+
Path path = prefixDir.resolve(fileName).normalize();
128+
if (!path.startsWith(prefixDir)) {
129+
throw new IllegalArgumentException("Invalid file name: " + fileName);
130+
}
126131
try (InputStream in = Files.newInputStream(path)) {
127132
return ByteStreams.toByteArray(in);
128133
}
129-
catch (FileNotFoundException ex) {
134+
catch (FileNotFoundException | NoSuchFileException ex) {
130135
throw new StorageFileNotFoundException(ex);
131136
}
132137
catch (IOException ex) {

digdag-core/src/test/java/io/digdag/core/log/LocalFileLogServerFactoryTest.java

+28
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import io.digdag.core.agent.AgentId;
77
import io.digdag.core.config.PropertyUtils;
88
import io.digdag.spi.LogFilePrefix;
9+
import io.digdag.spi.StorageFileNotFoundException;
910
import org.junit.Before;
1011
import org.junit.Rule;
1112
import org.junit.Test;
@@ -23,6 +24,7 @@
2324
import java.util.Properties;
2425

2526
import static java.nio.charset.StandardCharsets.UTF_8;
27+
import static org.junit.Assert.assertThrows;
2628

2729
import io.digdag.core.log.LocalFileLogServerFactory.LocalFileLogServer.LocalFileDirectTaskLogger;
2830

@@ -142,4 +144,30 @@ private String repeatedString(String v, int num)
142144
}
143145
return b.toString();
144146
}
147+
148+
@Test
149+
public void testGetFile() throws StorageFileNotFoundException
150+
{
151+
setUpTaskLogger(Optional.absent());
152+
String fileName = localServer.putFile(prefix, "+task", Instant.now(), "agent", "foo".getBytes(UTF_8));
153+
byte[] data = localServer.getFile(prefix, fileName);
154+
assertThat(new String(data, UTF_8), is("foo"));
155+
}
156+
157+
@Test
158+
public void testGetFileNotFound()
159+
{
160+
setUpTaskLogger(Optional.absent());
161+
assertThrows(StorageFileNotFoundException.class, () -> localServer.getFile(prefix, "foo"));
162+
}
163+
164+
@Test
165+
public void testGetFileInvalidFileName()
166+
{
167+
setUpTaskLogger(Optional.absent());
168+
assertThrows(IllegalArgumentException.class, () -> localServer.getFile(prefix, ".."));
169+
assertThrows(IllegalArgumentException.class, () -> localServer.getFile(prefix, "../foo"));
170+
assertThrows(IllegalArgumentException.class, () -> localServer.getFile(prefix, "/foo"));
171+
assertThrows(IllegalArgumentException.class, () -> localServer.getFile(prefix, "foo/../../bar"));
172+
}
145173
}

digdag-tests/src/test/java/acceptance/LogIT.java

+6
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@
1010
import utils.CommandStatus;
1111
import utils.TemporaryDigdagServer;
1212

13+
import javax.ws.rs.BadRequestException;
14+
import javax.ws.rs.NotFoundException;
1315
import java.nio.file.Files;
1416
import java.nio.file.Path;
1517
import java.util.regex.Pattern;
1618

1719
import static org.hamcrest.MatcherAssert.assertThat;
1820
import static org.hamcrest.Matchers.is;
21+
import static org.junit.Assert.assertThrows;
1922
import static org.junit.Assert.assertTrue;
2023
import static utils.TestUtils.*;
2124

@@ -91,5 +94,8 @@ public void verifyLogWithAttemptIdAndSessionId()
9194

9295
final String regex = "\\[\\d+:\\w+:\\d+:\\d+]";
9396
assertTrue(Pattern.compile(regex, Pattern.DOTALL).matcher(logs).find());
97+
98+
assertThrows(NotFoundException.class, () -> client.getLogFile(attemptId, "foo"));
99+
assertThrows(BadRequestException.class, () -> client.getLogFile(attemptId, "/foo"));
94100
}
95101
}

0 commit comments

Comments
 (0)