This is an automated email from the ASF dual-hosted git repository.

tballison pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tika.git


The following commit(s) were added to refs/heads/main by this push:
     new d8693a68c7 require application/json on tika-server /pipes and /async 
(#3442)
d8693a68c7 is described below

commit d8693a68c70b78653e0613979eeea552bafe775f
Author: Naveed <[email protected]>
AuthorDate: Fri Oct 30 21:05:58 2026 +0530

    require application/json on tika-server /pipes and /async (#3442)
    
    Without @Consumes both handlers read the tuple JSON under any
    Content-Type, so a browser can submit one cross-site as a text/plain,
    form-urlencoded or untyped POST with no CORS preflight.
    
    Generated-by: Claude Code
---
 .../tika/server/core/resource/AsyncResource.java   |  2 ++
 .../tika/server/core/resource/PipesResource.java   |  2 ++
 .../apache/tika/server/core/AsyncResourceTest.java |  1 +
 .../tika/server/core/PipesRequestLimitsTest.java   |  1 +
 .../org/apache/tika/server/core/TikaPipesTest.java | 36 ++++++++++++++++++++++
 .../core/TikaServerPipesIntegrationTest.java       |  3 ++
 .../apache/tika/server/standard/TikaPipesTest.java |  4 +++
 7 files changed, 49 insertions(+)

diff --git 
a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/AsyncResource.java
 
b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/AsyncResource.java
index a5de82d0e6..3fc243bbff 100644
--- 
a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/AsyncResource.java
+++ 
b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/AsyncResource.java
@@ -26,6 +26,7 @@ import java.util.Map;
 import java.util.concurrent.ArrayBlockingQueue;
 
 import jakarta.ws.rs.BadRequestException;
+import jakarta.ws.rs.Consumes;
 import jakarta.ws.rs.POST;
 import jakarta.ws.rs.Path;
 import jakarta.ws.rs.Produces;
@@ -109,6 +110,7 @@ public class AsyncResource {
      * @throws Exception
      */
     @POST
+    @Consumes("application/json")
     @Produces("application/json")
     public Response post(InputStream is, @Context HttpHeaders httpHeaders, 
@Context UriInfo info) throws Exception {
 
diff --git 
a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/PipesResource.java
 
b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/PipesResource.java
index b7f8081a3d..9a6bc79060 100644
--- 
a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/PipesResource.java
+++ 
b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/PipesResource.java
@@ -25,6 +25,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import jakarta.ws.rs.BadRequestException;
+import jakarta.ws.rs.Consumes;
 import jakarta.ws.rs.POST;
 import jakarta.ws.rs.Path;
 import jakarta.ws.rs.Produces;
@@ -84,6 +85,7 @@ public class PipesResource {
      * @throws Exception
      */
     @POST
+    @Consumes("application/json")
     @Produces("application/json")
     public Response postRmeta(InputStream is, @Context HttpHeaders 
httpHeaders, @Context UriInfo info) throws Exception {
         FetchEmitTuple t = null;
diff --git 
a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/AsyncResourceTest.java
 
b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/AsyncResourceTest.java
index aa5d2a8b7f..8e8dd373a8 100644
--- 
a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/AsyncResourceTest.java
+++ 
b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/AsyncResourceTest.java
@@ -135,6 +135,7 @@ public class AsyncResourceTest extends CXFTestBase {
         return WebClient
                 .create(endPoint + ASYNC_PATH)
                 .accept("application/json")
+                .type("application/json")
                 .post(body);
     }
 
diff --git 
a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/PipesRequestLimitsTest.java
 
b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/PipesRequestLimitsTest.java
index 8a9690eac3..1053eabe2f 100644
--- 
a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/PipesRequestLimitsTest.java
+++ 
b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/PipesRequestLimitsTest.java
@@ -141,6 +141,7 @@ public class PipesRequestLimitsTest extends CXFTestBase {
         Response response = WebClient
                 .create(endPoint + "/pipes")
                 .accept("application/json")
+                .type("application/json")
                 .post(tuple);
         assertEquals(200, response.getStatus());
 
diff --git 
a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaPipesTest.java
 
b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaPipesTest.java
index 8a6657358d..d45b687253 100644
--- 
a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaPipesTest.java
+++ 
b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaPipesTest.java
@@ -26,6 +26,10 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
 import java.io.StringWriter;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -194,6 +198,7 @@ public class TikaPipesTest extends CXFTestBase {
         Response response = WebClient
                 .create(getUrl)
                 .accept("application/json")
+                .type("application/json")
                 .post(writer.toString());
         assertEquals(200, response.getStatus());
 
@@ -234,6 +239,7 @@ public class TikaPipesTest extends CXFTestBase {
         Response response = WebClient
                 .create(getUrl)
                 .accept("application/json")
+                .type("application/json")
                 .post(writer.toString());
         assertEquals(200, response.getStatus());
 
@@ -265,6 +271,7 @@ public class TikaPipesTest extends CXFTestBase {
         Response response = WebClient
                 .create(getUrl)
                 .accept("application/json")
+                .type("application/json")
                 .post(writer.toString());
         assertEquals(200, response.getStatus());
 
@@ -299,6 +306,7 @@ public class TikaPipesTest extends CXFTestBase {
         Response response = WebClient
                 .create(getUrl)
                 .accept("application/json")
+                .type("application/json")
                 .post(writer.toString());
         assertEquals(200, response.getStatus());
 
@@ -334,6 +342,7 @@ public class TikaPipesTest extends CXFTestBase {
         return WebClient
                 .create(endPoint + PIPES_PATH)
                 .accept("application/json")
+                .type("application/json")
                 .post(writer.toString());
     }
 
@@ -370,6 +379,7 @@ public class TikaPipesTest extends CXFTestBase {
         Response response = WebClient
                 .create(endPoint + PIPES_PATH)
                 .accept("application/json")
+                .type("application/json")
                 .post("this is not json");
         assertEquals(400, response.getStatus());
         assertContains("/pipes request body",
@@ -383,10 +393,36 @@ public class TikaPipesTest extends CXFTestBase {
         Response response = WebClient
                 .create(endPoint + PIPES_PATH)
                 .accept("application/json")
+                .type("application/json")
                 .post(body);
         assertEquals(400, response.getStatus());
         assertContains("bogusField",
                 getStringFromInputStream((InputStream) response.getEntity()));
     }
 
+    /**
+     * A web page can POST to /pipes without a CORS preflight only with a 
text/plain,
+     * form-urlencoded or multipart content type, or with none at all; 
refusing those
+     * keeps a browser on the server's network from running tuples cross-site.
+     */
+    @Test
+    public void testCrossSiteSimpleRequestIsRefused() throws Exception {
+        FetchEmitTuple t = new FetchEmitTuple("myId",
+                new FetchKey(FETCHER_ID, HELLO_WORLD), new 
EmitKey(EMITTER_JSON_ID, ""), new Metadata());
+        StringWriter writer = new StringWriter();
+        JsonFetchEmitTuple.toJson(t, writer);
+        HttpClient client = HttpClient.newHttpClient();
+        for (String contentType : new String[]{"text/plain", 
"application/x-www-form-urlencoded", null}) {
+            HttpRequest.Builder request = HttpRequest
+                    .newBuilder(URI.create(endPoint + PIPES_PATH))
+                    
.POST(HttpRequest.BodyPublishers.ofString(writer.toString()));
+            if (contentType != null) {
+                request.header("Content-Type", contentType);
+            }
+            HttpResponse<String> response = client.send(request.build(), 
HttpResponse.BodyHandlers.ofString());
+            assertEquals(415, response.statusCode(), 
String.valueOf(contentType));
+            assertFalse(Files.exists(tmpOutputFile), 
String.valueOf(contentType));
+        }
+    }
+
 }
diff --git 
a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaServerPipesIntegrationTest.java
 
b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaServerPipesIntegrationTest.java
index 7c4cdedebc..b96e352b91 100644
--- 
a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaServerPipesIntegrationTest.java
+++ 
b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaServerPipesIntegrationTest.java
@@ -125,6 +125,7 @@ public class TikaServerPipesIntegrationTest extends 
IntegrationTestBase {
         Response response = WebClient
                 .create(endPoint + "/pipes")
                 .accept("application/json")
+                .type("application/json")
                 .post(getJsonStringWithTimeout(fileName, timeoutMillis));
         assertEquals(expectedStatus, response.getStatus());
         // a crash emits nothing, even with ON_PARSE_EXCEPTION.EMIT
@@ -160,6 +161,7 @@ public class TikaServerPipesIntegrationTest extends 
IntegrationTestBase {
         Response response = WebClient
                 .create(endPoint + "/pipes")
                 .accept("application/json")
+                .type("application/json")
                 .post(getJsonString(fileName, onParseException));
         assertEquals(expectedStatus, response.getStatus());
         Path targFile = TEMP_OUTPUT_DIR.resolve(fileName + ".json");
@@ -189,6 +191,7 @@ public class TikaServerPipesIntegrationTest extends 
IntegrationTestBase {
         Response response = WebClient
                 .create(endPoint + "/pipes")
                 .accept("application/json")
+                .type("application/json")
                 .post(requestJson);
         assertTrue(response.getStatus() != 200,
                 "parser injection must be rejected, got HTTP " + 
response.getStatus());
diff --git 
a/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/TikaPipesTest.java
 
b/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/TikaPipesTest.java
index 8a28798698..07cf61c096 100644
--- 
a/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/TikaPipesTest.java
+++ 
b/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/TikaPipesTest.java
@@ -204,6 +204,7 @@ public class TikaPipesTest extends CXFTestBase {
         Response response = WebClient
                 .create(getUrl)
                 .accept("application/json")
+                .type("application/json")
                 .post(writer.toString());
         assertEquals(200, response.getStatus());
 
@@ -233,6 +234,7 @@ public class TikaPipesTest extends CXFTestBase {
         Response response = WebClient
                 .create(getUrl)
                 .accept("application/json")
+                .type("application/json")
                 .post(writer.toString());
         assertEquals(200, response.getStatus());
 
@@ -262,6 +264,7 @@ public class TikaPipesTest extends CXFTestBase {
         Response response = WebClient
                 .create(getUrl)
                 .accept("application/json")
+                .type("application/json")
                 .post(writer.toString());
         assertEquals(200, response.getStatus());
 
@@ -315,6 +318,7 @@ public class TikaPipesTest extends CXFTestBase {
         Response response = WebClient
                 .create(getUrl)
                 .accept("application/json")
+                .type("application/json")
                 .post(writer.toString());
         assertEquals(200, response.getStatus());
 

Reply via email to