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());