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 f235aae182 require enableUnsecureFeatures in /pipes and /async 
handlers (#2902)
f235aae182 is described below

commit f235aae1822f90c023937548d3d95b60b56d92a1
Author: Tim Allison <[email protected]>
AuthorDate: Wed Jun 24 20:38:46 2026 -0400

    require enableUnsecureFeatures in /pipes and /async handlers (#2902)
---
 .../integration-testing/run-uat-script.adoc        |  3 +-
 .../advanced/integration-testing/tika-server.adoc  | 17 +++++++++
 docs/modules/ROOT/pages/advanced/robustness.adoc   |  2 +-
 .../migration-to-4x/migrating-tika-server-4x.adoc  | 16 +++++++++
 .../ROOT/pages/using-tika/server/index.adoc        | 21 +++++++++++-
 .../apache/tika/server/core/TikaServerConfig.java  | 25 ++++++++++++++
 .../tika/server/core/TikaServerConfigTest.java     | 40 ++++++++++++++++++++++
 .../configs/tika-config-server-basic.json          |  1 +
 .../configs/tika-config-server-emitter.json        |  2 +-
 .../configs/tika-config-server-pipes-basic.json    |  1 +
 ...n => tika-config-server-pipes-no-unsecure.json} | 15 ++------
 11 files changed, 127 insertions(+), 16 deletions(-)

diff --git 
a/docs/modules/ROOT/pages/advanced/integration-testing/run-uat-script.adoc 
b/docs/modules/ROOT/pages/advanced/integration-testing/run-uat-script.adoc
index 594e9e91ff..900cfedbc2 100644
--- a/docs/modules/ROOT/pages/advanced/integration-testing/run-uat-script.adoc
+++ b/docs/modules/ROOT/pages/advanced/integration-testing/run-uat-script.adoc
@@ -52,7 +52,8 @@ Coverage includes:
 * `/language/stream`
 * `/meta/form`, `/rmeta/form` (multipart variants)
 * `enableUnsecureFeatures=false` gating: `/meta/config`, `/rmeta/config`,
-  `/tika/config` all return 403
+  `/tika/config` all return 403; and selecting the `/pipes`, `/async`, or 
`/status`
+  endpoints without `enableUnsecureFeatures` makes the server refuse to start
 * `X-Tika-OCRskipOcr` header, `Content-Disposition` filename
 * 404 / 405 error handling
 
diff --git 
a/docs/modules/ROOT/pages/advanced/integration-testing/tika-server.adoc 
b/docs/modules/ROOT/pages/advanced/integration-testing/tika-server.adoc
index 2608a6b490..d42d0a0644 100644
--- a/docs/modules/ROOT/pages/advanced/integration-testing/tika-server.adoc
+++ b/docs/modules/ROOT/pages/advanced/integration-testing/tika-server.adoc
@@ -214,6 +214,23 @@ curl -s -w "\nHTTP Status: %{http_code}\n" -X POST -F 
"[email protected]" http:/
 
 *Expected:* All return HTTP 403 with message: "Config endpoints are disabled. 
Set enableUnsecureFeatures=true in server config."
 
+=== Test 18b: `/pipes`, `/async`, `/status` Require enableUnsecureFeatures
+
+[source,bash]
+----
+cat > tika-config-pipes-no-unsecure.json << 'EOF'
+{
+  "server": {"port": 9998, "endpoints": ["tika", "pipes"]},
+  "pipes": {"numClients": 2},
+  "plugin-roots": "/tmp/tika-server-test/plugins"
+}
+EOF
+
+java -jar tika-server-standard-4.0.0-SNAPSHOT.jar -c 
tika-config-pipes-no-unsecure.json
+----
+
+*Expected:* The server refuses to start, failing with a `TikaConfigException` 
stating that the `pipes` endpoint requires `enableUnsecureFeatures` to be 
`true`. The same applies to `async` and `status`.
+
 == Part 2: Tests with enableUnsecureFeatures
 
 Stop the default server and create a config file:
diff --git a/docs/modules/ROOT/pages/advanced/robustness.adoc 
b/docs/modules/ROOT/pages/advanced/robustness.adoc
index 784ba02463..170db7cf27 100644
--- a/docs/modules/ROOT/pages/advanced/robustness.adoc
+++ b/docs/modules/ROOT/pages/advanced/robustness.adoc
@@ -97,7 +97,7 @@ tika-server restarts gracefully.
 
 tika-pipes::
 Available through programmatic use, tika-app `-a` option, or tika-server's 
`/async`
-and `/pipes` endpoints.
+and `/pipes` endpoints (the server endpoints require 
`enableUnsecureFeatures=true`).
 
 == Security Testing and Prevention
 
diff --git 
a/docs/modules/ROOT/pages/migration-to-4x/migrating-tika-server-4x.adoc 
b/docs/modules/ROOT/pages/migration-to-4x/migrating-tika-server-4x.adoc
index 4a18868ec4..59e8691e76 100644
--- a/docs/modules/ROOT/pages/migration-to-4x/migrating-tika-server-4x.adoc
+++ b/docs/modules/ROOT/pages/migration-to-4x/migrating-tika-server-4x.adoc
@@ -132,6 +132,22 @@ The following `TikaServerConfig` options have been removed:
 
 * **Fetcher-based streaming** - The `InputStreamFactory` pattern for fetching 
documents via HTTP headers (`fetcherName`, `fetchKey`) has been removed. All 
documents are now processed via temp files through the pipes infrastructure.
 
+=== `/pipes`, `/async`, and `/status` Require `enableUnsecureFeatures`
+
+Previously these endpoints were enabled simply by listing them under 
`server.endpoints`. They now *also* require `enableUnsecureFeatures` to be 
`true`; selecting any of `pipes`, `async`, or `status` without it causes the 
server to refuse to start with a clear error. `/pipes` and `/async` drive 
process-isolated batch parsing through your fetchers and emitters, and 
`/status` exposes server information, so this makes enabling them an explicit, 
deliberate opt-in.
+
+**Migration:** if your config selects `pipes`, `async`, or `status`, add 
`"enableUnsecureFeatures": true` to the `server` section:
+
+[source,json]
+----
+{
+  "server": {
+    "enableUnsecureFeatures": true,
+    "endpoints": ["tika", "rmeta", "pipes", "async", "status"]
+  }
+}
+----
+
 == Configuration Changes
 
 === Required: Pipes Configuration
diff --git a/docs/modules/ROOT/pages/using-tika/server/index.adoc 
b/docs/modules/ROOT/pages/using-tika/server/index.adoc
index 0c92d3e60f..ecec41df26 100644
--- a/docs/modules/ROOT/pages/using-tika/server/index.adoc
+++ b/docs/modules/ROOT/pages/using-tika/server/index.adoc
@@ -156,6 +156,11 @@ curl -T document.pdf 
http://localhost:9998/meta/Content-Type   # single field
 * `/translate/all/\{translator}/\{src}/\{dest}` — translation
 * `/pipes`, `/async` — Pipes-based bulk processing
 
+NOTE: `/pipes`, `/async`, and `/status` expose unsecure features and are only 
available
+when `enableUnsecureFeatures` is `true` (see <<_security_configuration,Security
+Configuration>>). Selecting any of them without that flag causes the server to 
refuse
+to start.
+
 == Error Responses
 
 When parsing fails due to a process-level problem — the forked child process 
timed out,
@@ -207,7 +212,7 @@ Server behavior beyond host/port is controlled by a JSON 
config file passed via
 
 |`enableUnsecureFeatures`
 |`false`
-|Enable the `/config` family of endpoints (see 
<<_security_configuration,Security Configuration>>).
+|Required opt-in for unsecure features: the `/config` family of endpoints and 
the `/pipes`, `/async`, and `/status` endpoints. The server refuses to start if 
any of those endpoints are selected without this flag (see 
<<_security_configuration,Security Configuration>>).
 
 |`cors`
 |`""` (off)
@@ -279,6 +284,20 @@ xref:using-tika/server/tls.adoc[2-way TLS authentication]. 
Exposing config endpo
 to untrusted networks can help attackers identify vulnerabilities and craft
 targeted attacks.
 
+=== Pipes, Async, and Status Endpoints
+
+The `/pipes`, `/async`, and `/status` endpoints also require 
`enableUnsecureFeatures`.
+`/pipes` and `/async` drive process-isolated batch parsing through your 
configured
+fetchers and emitters — whoever can reach them gains the read access of your 
fetchers
+and the write access of your emitters (see
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-3271[CVE-2015-3271]); 
`/status`
+exposes server information.
+
+In earlier releases these endpoints were enabled simply by listing them under
+`server.endpoints`. You must now *also* set `enableUnsecureFeatures` to `true`;
+selecting any of them without it causes the server to refuse to start. This is
+deliberate — it makes enabling these powerful endpoints an explicit, 
considered choice.
+
 === Security Best Practices
 
 1. **Keep config endpoints disabled** in production (default behavior).
diff --git 
a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TikaServerConfig.java
 
b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TikaServerConfig.java
index fa7bb3f93d..6eb1771af7 100644
--- 
a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TikaServerConfig.java
+++ 
b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TikaServerConfig.java
@@ -58,6 +58,13 @@ public class TikaServerConfig {
                     "Additionally, /config endpoints allow per-request parser 
configuration\n" +
                     "which could enable dangerous operations.\n" +
                     "Please make sure you know what you are doing.";
+    /**
+     * Endpoints that expose unsecure features (process-isolated pipes 
parsing, async
+     * batch processing, and server status). Selecting any of these now 
requires
+     * {@code enableUnsecureFeatures=true} as an explicit, deliberate opt-in.
+     */
+    private static final Set<String> ENDPOINTS_REQUIRING_UNSECURE_FEATURES =
+            new HashSet<>(Arrays.asList("pipes", "async", "status"));
     private static final List<String> ONLY_IN_FORK_MODE = Arrays.asList(
             new String[]{"maxFiles", "javaPath", "maxRestarts", "numRestarts", 
"forkedStatusFile", "maxForkedStartupMillis",
                     "tmpFilePrefix"});
@@ -168,6 +175,24 @@ private long forkedProcessShutdownMillis = 
DEFAULT_FORKED_PROCESS_SHUTDOWN_MILLI
         if (host == null) {
             throw new TikaConfigException("Must specify 'host'");
         }
+        if (!enableUnsecureFeatures) {
+            List<String> requireUnsecure = new ArrayList<>();
+            for (String endpoint : endpoints) {
+                if (ENDPOINTS_REQUIRING_UNSECURE_FEATURES.contains(endpoint)
+                        && !requireUnsecure.contains(endpoint)) {
+                    requireUnsecure.add(endpoint);
+                }
+            }
+            if (!requireUnsecure.isEmpty()) {
+                throw new TikaConfigException(
+                        "The following selected endpoint(s) require unsecure 
features to be " +
+                        "enabled: " + requireUnsecure + ". Set 
'enableUnsecureFeatures' to true " +
+                        "in the 'server' section of your tika-config and 
confirm you understand " +
+                        "the security implications (see the tika-server 
documentation). These " +
+                        "endpoints were previously enabled simply by selecting 
them; the explicit " +
+                        "opt-in is now required.");
+            }
+        }
     }
 
     public String getHost() {
diff --git 
a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaServerConfigTest.java
 
b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaServerConfigTest.java
index 411317d6ef..d4920f04fe 100644
--- 
a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaServerConfigTest.java
+++ 
b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaServerConfigTest.java
@@ -18,6 +18,7 @@ package org.apache.tika.server.core;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.nio.file.Path;
@@ -32,6 +33,7 @@ import org.apache.commons.cli.Options;
 import org.junit.jupiter.api.Test;
 
 import org.apache.tika.TikaTest;
+import org.apache.tika.exception.TikaConfigException;
 import org.apache.tika.utils.ProcessUtils;
 
 public class TikaServerConfigTest extends TikaTest {
@@ -76,6 +78,44 @@ public class TikaServerConfigTest extends TikaTest {
         TikaServerConfig config = TikaServerConfig.load(commandLine);
     }
 
+    @Test
+    public void testUnsecureEndpointRequiresEnableUnsecureFeatures() throws 
Exception {
+        // Selecting /pipes (or /async, /status) without 
enableUnsecureFeatures must fail
+        // at config load, forcing an explicit opt-in.
+        CommandLineParser parser = new DefaultParser();
+        Path path = getConfigPath(getClass(), 
"tika-config-server-pipes-no-unsecure.json");
+        CommandLine commandLine = parser.parse(new Options()
+                .addOption(Option
+                        .builder("c")
+                        .longOpt("config")
+                        .hasArg()
+                        .get()), new String[]{"-c", 
ProcessUtils.escapeCommandLine(path
+                .toAbsolutePath()
+                .toString())});
+        TikaConfigException ex = assertThrows(TikaConfigException.class,
+                () -> TikaServerConfig.load(commandLine));
+        assertContains("enableUnsecureFeatures", ex.getMessage());
+        assertContains("pipes", ex.getMessage());
+    }
+
+    @Test
+    public void testUnsecureEndpointAllowedWithEnableUnsecureFeatures() throws 
Exception {
+        // tika-config-server-basic.json selects the 'status' endpoint 
together with
+        // enableUnsecureFeatures=true, so it must load without error.
+        CommandLineParser parser = new DefaultParser();
+        Path path = getConfigPath(getClass(), "tika-config-server-basic.json");
+        CommandLine commandLine = parser.parse(new Options()
+                .addOption(Option
+                        .builder("c")
+                        .longOpt("config")
+                        .hasArg()
+                        .get()), new String[]{"-c", 
ProcessUtils.escapeCommandLine(path
+                .toAbsolutePath()
+                .toString())});
+        TikaServerConfig config = TikaServerConfig.load(commandLine);
+        assertTrue(config.isEnableUnsecureFeatures());
+    }
+
     @Test
     public void testTlsConfig() throws Exception {
         Set<String> settings = new HashSet<>();
diff --git 
a/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-basic.json
 
b/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-basic.json
index a14eda47ae..41d8acb90b 100644
--- 
a/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-basic.json
+++ 
b/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-basic.json
@@ -8,6 +8,7 @@
   },
   "server": {
     "port": 9999,
+    "enableUnsecureFeatures": true,
     "endpoints": [
       "rmeta",
       "status",
diff --git 
a/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-emitter.json
 
b/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-emitter.json
index ce5f4a6f51..60a672a866 100644
--- 
a/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-emitter.json
+++ 
b/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-emitter.json
@@ -8,7 +8,7 @@
   },
   "server": {
     "port": 9999,
-    "enableUnsecure": true,
+    "enableUnsecureFeatures": true,
     "endpoints": [
       "emit",
       "async",
diff --git 
a/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-pipes-basic.json
 
b/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-pipes-basic.json
index 86a24fa4c3..2b7ed5a22b 100644
--- 
a/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-pipes-basic.json
+++ 
b/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-pipes-basic.json
@@ -8,6 +8,7 @@
   },
   "server": {
     "port": 9999,
+    "enableUnsecureFeatures": true,
     "endpoints": [
       "rmeta",
       "status",
diff --git 
a/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-pipes-basic.json
 
b/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-pipes-no-unsecure.json
similarity index 55%
copy from 
tika-server/tika-server-core/src/test/resources/configs/tika-config-server-pipes-basic.json
copy to 
tika-server/tika-server-core/src/test/resources/configs/tika-config-server-pipes-no-unsecure.json
index 86a24fa4c3..262f29d7a8 100644
--- 
a/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-pipes-basic.json
+++ 
b/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-pipes-no-unsecure.json
@@ -9,21 +9,12 @@
   "server": {
     "port": 9999,
     "endpoints": [
-      "rmeta",
-      "status",
-      "tika"
+      "tika",
+      "pipes"
     ]
   },
-  "parse-context": {
-    "timeout-limits": {
-      "progressTimeoutMillis": 5000
-    }
-  },
   "pipes": {
-    "numClients": 2,
-    "forkedJvmArgs": [
-      "-Xmx256m"
-    ]
+    "numClients": 2
   },
   "plugin-roots": "target/plugins"
 }

Reply via email to