This is an automated email from the ASF dual-hosted git repository. tballison pushed a commit to branch TIKA-4809-stage-9 in repository https://gitbox.apache.org/repos/asf/tika.git
commit 59df216d8d671c5458a8b0f5f48ff0ea6a645e6e Author: tallison <[email protected]> AuthorDate: Mon Aug 10 14:14:22 2026 -0400 TIKA-4809: Stop reporting the server's spool filename as the document's identity --- .../server/core/resource/PipesParsingHelper.java | 29 ++++++++++++++++++ .../apache/tika/server/core/TikaResourceTest.java | 34 ++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/PipesParsingHelper.java b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/PipesParsingHelper.java index 0b61676b14..fe8c50f2b8 100644 --- a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/PipesParsingHelper.java +++ b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/PipesParsingHelper.java @@ -127,6 +127,7 @@ public class PipesParsingHelper { ParseContext parseContext, ParseMode parseMode) throws IOException { String requestId = UUID.randomUUID().toString(); Path tempFile = null; + String callerSuppliedName = metadata.get(TikaCoreProperties.RESOURCE_NAME_KEY); try { // Spool input to our dedicated temp directory with proper suffix @@ -162,6 +163,7 @@ public class PipesParsingHelper { // Process result List<Metadata> metadataList = processResult(result); + stripSpoolIdentity(metadataList, relativeName, callerSuppliedName); return metadataList; } catch (InterruptedException e) { @@ -181,6 +183,31 @@ public class PipesParsingHelper { } } + /** + * Removes the server's spool filename from the returned metadata. + * <p> + * The document is fetched from a temp file, so the fetcher records that path as + * {@code tk:source-path} and, when the caller supplied no filename, it also becomes + * {@code tk:resource-name} -- the field downstream consumers key document identity on. + * Neither describes the caller's document: they name a file that has already been + * deleted, and they expose the server's spooling scheme. + */ + private static void stripSpoolIdentity(List<Metadata> metadataList, String spoolName, + String callerSuppliedName) { + if (metadataList == null) { + return; + } + for (Metadata m : metadataList) { + if (spoolName.equals(m.get(TikaCoreProperties.SOURCE_PATH))) { + m.remove(TikaCoreProperties.SOURCE_PATH.getName()); + } + if (callerSuppliedName == null + && spoolName.equals(m.get(TikaCoreProperties.RESOURCE_NAME_KEY))) { + m.remove(TikaCoreProperties.RESOURCE_NAME_KEY.getName()); + } + } + } + /** * Extracts file suffix from metadata (resource name or content-type). */ @@ -348,6 +375,7 @@ public class PipesParsingHelper { ParseContext parseContext, boolean saveAll) throws IOException { String requestId = UUID.randomUUID().toString(); Path tempFile = null; + String callerSuppliedName = metadata.get(TikaCoreProperties.RESOURCE_NAME_KEY); try { // Spool input to our dedicated temp directory with proper suffix @@ -452,6 +480,7 @@ public class PipesParsingHelper { boolean isFrictionless = unpackConfig.getOutputFormat() == UnpackConfig.OUTPUT_FORMAT.FRICTIONLESS; Path zipFile = getEmittedZipPath(requestId, isFrictionless); + stripSpoolIdentity(metadataList, relativeName, callerSuppliedName); return new UnpackResult(zipFile, metadataList); } finally { // Clean up temp file diff --git a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaResourceTest.java b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaResourceTest.java index 94eb1bf756..d41cd8143b 100644 --- a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaResourceTest.java +++ b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaResourceTest.java @@ -17,6 +17,7 @@ package org.apache.tika.server.core; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.InputStream; @@ -214,4 +215,37 @@ public class TikaResourceTest extends CXFTestBase { } }*/ + /** + * The document is spooled to a temp file, so without this the fetcher's path is what + * comes back as tk:source-path -- and, absent a client filename, as tk:resource-name, + * which is the field downstream consumers key document identity on. + */ + @Test + public void testSpoolNameDoesNotLeak() throws Exception { + Response response = WebClient + .create(endPoint + TIKA_PATH + "/json") + .put(ClassLoader.getSystemResourceAsStream(TEST_HELLO_WORLD)); + Metadata metadata = JsonMetadata.fromJson(new InputStreamReader( + (InputStream) response.getEntity(), StandardCharsets.UTF_8)); + + assertNull(metadata.get(TikaCoreProperties.SOURCE_PATH), + "the server's spool path must not be reported to the caller"); + String name = metadata.get(TikaCoreProperties.RESOURCE_NAME_KEY); + assertTrue(name == null || !name.startsWith("tika-"), + "no client filename was sent, so the spool name must not stand in as one: " + name); + } + + /** A filename the caller did supply is theirs, and must survive. */ + @Test + public void testClientFilenameIsPreserved() throws Exception { + Response response = WebClient + .create(endPoint + TIKA_PATH + "/json") + .header("Content-Disposition", "attachment; filename=\"my-report.xml\"") + .put(ClassLoader.getSystemResourceAsStream(TEST_HELLO_WORLD)); + Metadata metadata = JsonMetadata.fromJson(new InputStreamReader( + (InputStream) response.getEntity(), StandardCharsets.UTF_8)); + + assertEquals("my-report.xml", metadata.get(TikaCoreProperties.RESOURCE_NAME_KEY)); + } + }
