From bb1bdee3bde3cad24388b3cea5c059c11f59bef6 Mon Sep 17 00:00:00 2001 From: Ayush Saxena Date: Thu, 30 Oct 2025 13:13:53 +0530 Subject: [PATCH 1/2] Restrict some paths in ProfileOutputServlet --- .../apache/tez/common/web/ProfileOutputServlet.java | 11 ++++++++++- .../src/test/java/org/apache/tez/test/TestAM.java | 5 +++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/tez-common/src/main/java/org/apache/tez/common/web/ProfileOutputServlet.java b/tez-common/src/main/java/org/apache/tez/common/web/ProfileOutputServlet.java index b95d878529..7d26f5db58 100644 --- a/tez-common/src/main/java/org/apache/tez/common/web/ProfileOutputServlet.java +++ b/tez-common/src/main/java/org/apache/tez/common/web/ProfileOutputServlet.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import javax.servlet.ServletException; @@ -43,7 +44,15 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro writeMessage(response, "Run the profiler to be able to receive its output"); return; } - File outputFile = new File(ProfileServlet.OUTPUT_DIR, queriedFile); + Path outputDir = Paths.get(ProfileServlet.OUTPUT_DIR).toAbsolutePath().normalize(); + Path requestedPath = outputDir.resolve(queriedFile).normalize(); + + if (!requestedPath.startsWith(outputDir)) { + writeMessage(response, "Access denied: Invalid Path"); + return; + } + File outputFile = requestedPath.toFile(); + if (!outputFile.exists()) { writeMessage(response, "Requested file does not exist: " + queriedFile); return; diff --git a/tez-tests/src/test/java/org/apache/tez/test/TestAM.java b/tez-tests/src/test/java/org/apache/tez/test/TestAM.java index 3338deb3d9..0edf2dbaf3 100644 --- a/tez-tests/src/test/java/org/apache/tez/test/TestAM.java +++ b/tez-tests/src/test/java/org/apache/tez/test/TestAM.java @@ -133,6 +133,11 @@ public void testAMWebUIService() throws TezException, IOException, InterruptedEx checkAddress(webUIAddress + "/prof", 202); checkAddress(webUIAddress + "/prof-output"); + HttpURLConnection connection = + (HttpURLConnection) new URL(webUIAddress + "/prof-output?file=../etc/web").openConnection(); + connection.connect(); + assertTrue(new String(connection.getInputStream().readAllBytes()).contains("Access denied: Invalid Path")); + URL url = new URL(webUIAddress); IntegerRanges portRange = conf.getRange(TezConfiguration.TEZ_AM_WEBSERVICE_PORT_RANGE, TezConfiguration.TEZ_AM_WEBSERVICE_PORT_RANGE_DEFAULT); From b6ca7a89e24dd2deccc14190a132f0ee3f59c6b9 Mon Sep 17 00:00:00 2001 From: Ayush Saxena Date: Fri, 31 Oct 2025 14:33:08 +0530 Subject: [PATCH 2/2] Add Response Code --- .../org/apache/tez/common/web/ProfileOutputServlet.java | 1 + tez-tests/src/test/java/org/apache/tez/test/TestAM.java | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tez-common/src/main/java/org/apache/tez/common/web/ProfileOutputServlet.java b/tez-common/src/main/java/org/apache/tez/common/web/ProfileOutputServlet.java index 7d26f5db58..e1b9d2f058 100644 --- a/tez-common/src/main/java/org/apache/tez/common/web/ProfileOutputServlet.java +++ b/tez-common/src/main/java/org/apache/tez/common/web/ProfileOutputServlet.java @@ -48,6 +48,7 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro Path requestedPath = outputDir.resolve(queriedFile).normalize(); if (!requestedPath.startsWith(outputDir)) { + response.setStatus(HttpServletResponse.SC_FORBIDDEN); writeMessage(response, "Access denied: Invalid Path"); return; } diff --git a/tez-tests/src/test/java/org/apache/tez/test/TestAM.java b/tez-tests/src/test/java/org/apache/tez/test/TestAM.java index 0edf2dbaf3..adfe18a9eb 100644 --- a/tez-tests/src/test/java/org/apache/tez/test/TestAM.java +++ b/tez-tests/src/test/java/org/apache/tez/test/TestAM.java @@ -17,6 +17,7 @@ */ package org.apache.tez.test; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -25,6 +26,8 @@ import java.net.HttpURLConnection; import java.net.URL; +import javax.servlet.http.HttpServletResponse; + import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration.IntegerRanges; import org.apache.hadoop.fs.FileSystem; @@ -136,7 +139,8 @@ public void testAMWebUIService() throws TezException, IOException, InterruptedEx HttpURLConnection connection = (HttpURLConnection) new URL(webUIAddress + "/prof-output?file=../etc/web").openConnection(); connection.connect(); - assertTrue(new String(connection.getInputStream().readAllBytes()).contains("Access denied: Invalid Path")); + assertEquals(HttpServletResponse.SC_FORBIDDEN, connection.getResponseCode()); + assertTrue(new String(connection.getErrorStream().readAllBytes()).contains("Access denied: Invalid Path")); URL url = new URL(webUIAddress); IntegerRanges portRange = conf.getRange(TezConfiguration.TEZ_AM_WEBSERVICE_PORT_RANGE,