This is an automated email from the ASF dual-hosted git repository. ptupitsyn pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push: new 5c42c7a3039 IGNITE-25524 Fix GridLogCommandHandler path validation (#12136) 5c42c7a3039 is described below commit 5c42c7a303937844179ad470edb35c1ad1cee6ab Author: Pavel Tupitsyn <ptupit...@apache.org> AuthorDate: Fri Jun 13 12:56:22 2025 +0300 IGNITE-25524 Fix GridLogCommandHandler path validation (#12136) --- .../rest/handlers/log/GridLogCommandHandler.java | 17 ++++--- .../handlers/log/GridLogCommandHandlerTest.java | 52 ++++++++++++++++++++-- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/log/GridLogCommandHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/log/GridLogCommandHandler.java index aac1fa7e188..ecb733ea995 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/log/GridLogCommandHandler.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/log/GridLogCommandHandler.java @@ -20,7 +20,7 @@ import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; -import java.nio.file.InvalidPathException; +import java.net.URI; import java.util.Collection; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.internal.GridKernalContext; @@ -36,7 +36,7 @@ import org.apache.ignite.internal.util.typedef.internal.U; import static org.apache.ignite.internal.processors.rest.GridRestCommand.LOG; /** - * Handler for {@link org.apache.ignite.internal.processors.rest.GridRestCommand#LOG} command. + * Handler for {@link GridRestCommand#LOG} command. */ public class GridLogCommandHandler extends GridRestCommandHandlerAdapter { /** @@ -120,7 +120,7 @@ public class GridLogCommandHandler extends GridRestCommandHandlerAdapter { else logFile = new File(req0.path()); } - else if (req0.path().startsWith(ctx.config().getIgniteHome())) + else if (resolveFilePath(req0.path()).startsWith(ctx.config().getIgniteHome())) logFile = new File(req0.path()); else { return new GridFinishedFuture<>(new GridRestResponse(GridRestResponse.STATUS_FAILED, @@ -132,7 +132,7 @@ public class GridLogCommandHandler extends GridRestCommandHandlerAdapter { else logFile = new File(log.fileName()); } - catch (InvalidPathException e) { + catch (Exception e) { return new GridFinishedFuture<>(new GridRestResponse(GridRestResponse.STATUS_FAILED, "Incorrect path to a log file [msg=" + e.getMessage() + ']')); } @@ -159,7 +159,7 @@ public class GridLogCommandHandler extends GridRestCommandHandlerAdapter { * @return Content that is read. * @throws IgniteCheckedException If failed. */ - private String readLog(int from, int to, File logFile) throws IgniteCheckedException { + private static String readLog(int from, int to, File logFile) throws IgniteCheckedException { StringBuilder content = new StringBuilder(); try (BufferedReader reader = new BufferedReader(new FileReader(logFile))) { @@ -184,4 +184,11 @@ public class GridLogCommandHandler extends GridRestCommandHandlerAdapter { return content.toString(); } + + /** */ + private static String resolveFilePath(String p) throws Exception { + p = new URI(p).normalize().getPath(); + + return new File(p).getCanonicalPath(); + } } diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/rest/handlers/log/GridLogCommandHandlerTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/rest/handlers/log/GridLogCommandHandlerTest.java index 4739051425a..5e9fc3d2cf5 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/rest/handlers/log/GridLogCommandHandlerTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/rest/handlers/log/GridLogCommandHandlerTest.java @@ -16,7 +16,7 @@ */ package org.apache.ignite.internal.processors.rest.handlers.log; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -38,7 +38,7 @@ import org.junit.Test; */ public class GridLogCommandHandlerTest extends GridCommonAbstractTest { /** */ - private String igniteHome = System.getProperty("user.dir"); + private final String igniteHome = System.getProperty("user.dir"); /** {@inheritDoc} */ @Override protected void beforeTestsStarted() throws Exception { @@ -53,11 +53,13 @@ public class GridLogCommandHandlerTest extends GridCommonAbstractTest { Files.createDirectories(dir); Path file = Paths.get(igniteHome + "/work/log/" + "ignite.log"); - Files.write(file, lines, Charset.forName("UTF-8")); + Files.write(file, lines, StandardCharsets.UTF_8); file = Paths.get(igniteHome + "/work/log/" + "test.log"); - Files.write(file, lines, Charset.forName("UTF-8")); + Files.write(file, lines, StandardCharsets.UTF_8); + file = Paths.get(igniteHome + "/../parent.txt"); + Files.write(file, "Should not be read.".getBytes(StandardCharsets.UTF_8)); } /** {@inheritDoc} */ @@ -65,6 +67,7 @@ public class GridLogCommandHandlerTest extends GridCommonAbstractTest { Files.delete(Paths.get(igniteHome + "/work/log/" + "test.log")); Files.delete(Paths.get(igniteHome + "/work/log/" + "ignite.log")); Files.delete(Paths.get(igniteHome + "/work/log/")); + Files.delete(Paths.get(igniteHome + "/../parent.txt")); } /** @@ -198,6 +201,47 @@ public class GridLogCommandHandlerTest extends GridCommonAbstractTest { assertNull(resp.result().getResponse()); } + /** + * @throws Exception If failed. + */ + @Test + public void testHandleAsyncPathWithIgniteHomeAndContainsParentDirectory() throws Exception { + testHandleAsyncPathWithIgniteHomeAndContainsParentDirectory(igniteHome + "/../parent.txt"); + + testHandleAsyncPathWithIgniteHomeAndContainsParentDirectory(igniteHome + "/.%2e/parent.txt"); + testHandleAsyncPathWithIgniteHomeAndContainsParentDirectory(igniteHome + "/%2e./parent.txt"); + testHandleAsyncPathWithIgniteHomeAndContainsParentDirectory(igniteHome + "/%2e%2e/parent.txt"); + + testHandleAsyncPathWithIgniteHomeAndContainsParentDirectory(igniteHome + "/.%252e/parent.txt"); + testHandleAsyncPathWithIgniteHomeAndContainsParentDirectory(igniteHome + "/%252e./parent.txt"); + testHandleAsyncPathWithIgniteHomeAndContainsParentDirectory(igniteHome + "/%252e%252e/parent.txt"); + + testHandleAsyncPathWithIgniteHomeAndContainsParentDirectory(igniteHome + "/%2e%252e/parent.txt"); + + testHandleAsyncPathWithIgniteHomeAndContainsParentDirectory(igniteHome + "/%00../parent.txt"); + testHandleAsyncPathWithIgniteHomeAndContainsParentDirectory(igniteHome + "/.%00./parent.txt"); + } + + /** + * @throws Exception If failed. + */ + private void testHandleAsyncPathWithIgniteHomeAndContainsParentDirectory(String p) throws Exception { + IgniteConfiguration cfg = new IgniteConfiguration(); + cfg.setIgniteHome(igniteHome); + GridTestKernalContext ctx = newContext(cfg); + GridLogCommandHandler cmdHnd = new GridLogCommandHandler(ctx); + GridRestLogRequest req = new GridRestLogRequest(); + + req.to(1); + req.from(0); + req.path(p); + + IgniteInternalFuture<GridRestResponse> resp = cmdHnd.handleAsync(req); + + assertEquals(GridRestResponse.STATUS_FAILED, resp.result().getSuccessStatus()); + assertNull(resp.result().getResponse()); + } + /** * @throws Exception If failed. */