Skip to content

Commit f235aae

Browse files
authored
require enableUnsecureFeatures in /pipes and /async handlers (#2902)
1 parent 841250d commit f235aae

11 files changed

Lines changed: 144 additions & 4 deletions

File tree

docs/modules/ROOT/pages/advanced/integration-testing/run-uat-script.adoc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ Coverage includes:
5252
* `/language/stream`
5353
* `/meta/form`, `/rmeta/form` (multipart variants)
5454
* `enableUnsecureFeatures=false` gating: `/meta/config`, `/rmeta/config`,
55-
`/tika/config` all return 403
55+
`/tika/config` all return 403; and selecting the `/pipes`, `/async`, or `/status`
56+
endpoints without `enableUnsecureFeatures` makes the server refuse to start
5657
* `X-Tika-OCRskipOcr` header, `Content-Disposition` filename
5758
* 404 / 405 error handling
5859

docs/modules/ROOT/pages/advanced/integration-testing/tika-server.adoc

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,23 @@ curl -s -w "\nHTTP Status: %{http_code}\n" -X POST -F "file=@testPDF.pdf" http:/
214214

215215
*Expected:* All return HTTP 403 with message: "Config endpoints are disabled. Set enableUnsecureFeatures=true in server config."
216216

217+
=== Test 18b: `/pipes`, `/async`, `/status` Require enableUnsecureFeatures
218+
219+
[source,bash]
220+
----
221+
cat > tika-config-pipes-no-unsecure.json << 'EOF'
222+
{
223+
"server": {"port": 9998, "endpoints": ["tika", "pipes"]},
224+
"pipes": {"numClients": 2},
225+
"plugin-roots": "/tmp/tika-server-test/plugins"
226+
}
227+
EOF
228+
229+
java -jar tika-server-standard-4.0.0-SNAPSHOT.jar -c tika-config-pipes-no-unsecure.json
230+
----
231+
232+
*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`.
233+
217234
== Part 2: Tests with enableUnsecureFeatures
218235

219236
Stop the default server and create a config file:

docs/modules/ROOT/pages/advanced/robustness.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ tika-server restarts gracefully.
9797

9898
tika-pipes::
9999
Available through programmatic use, tika-app `-a` option, or tika-server's `/async`
100-
and `/pipes` endpoints.
100+
and `/pipes` endpoints (the server endpoints require `enableUnsecureFeatures=true`).
101101

102102
== Security Testing and Prevention
103103

docs/modules/ROOT/pages/migration-to-4x/migrating-tika-server-4x.adoc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,22 @@ The following `TikaServerConfig` options have been removed:
132132
133133
* **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.
134134
135+
=== `/pipes`, `/async`, and `/status` Require `enableUnsecureFeatures`
136+
137+
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.
138+
139+
**Migration:** if your config selects `pipes`, `async`, or `status`, add `"enableUnsecureFeatures": true` to the `server` section:
140+
141+
[source,json]
142+
----
143+
{
144+
"server": {
145+
"enableUnsecureFeatures": true,
146+
"endpoints": ["tika", "rmeta", "pipes", "async", "status"]
147+
}
148+
}
149+
----
150+
135151
== Configuration Changes
136152
137153
=== Required: Pipes Configuration

docs/modules/ROOT/pages/using-tika/server/index.adoc

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ curl -T document.pdf http://localhost:9998/meta/Content-Type # single field
156156
* `/translate/all/\{translator}/\{src}/\{dest}` — translation
157157
* `/pipes`, `/async` — Pipes-based bulk processing
158158

159+
NOTE: `/pipes`, `/async`, and `/status` expose unsecure features and are only available
160+
when `enableUnsecureFeatures` is `true` (see <<_security_configuration,Security
161+
Configuration>>). Selecting any of them without that flag causes the server to refuse
162+
to start.
163+
159164
== Error Responses
160165

161166
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
207212

208213
|`enableUnsecureFeatures`
209214
|`false`
210-
|Enable the `/config` family of endpoints (see <<_security_configuration,Security Configuration>>).
215+
|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>>).
211216

212217
|`cors`
213218
|`""` (off)
@@ -279,6 +284,20 @@ xref:using-tika/server/tls.adoc[2-way TLS authentication]. Exposing config endpo
279284
to untrusted networks can help attackers identify vulnerabilities and craft
280285
targeted attacks.
281286

287+
=== Pipes, Async, and Status Endpoints
288+
289+
The `/pipes`, `/async`, and `/status` endpoints also require `enableUnsecureFeatures`.
290+
`/pipes` and `/async` drive process-isolated batch parsing through your configured
291+
fetchers and emitters — whoever can reach them gains the read access of your fetchers
292+
and the write access of your emitters (see
293+
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-3271[CVE-2015-3271]); `/status`
294+
exposes server information.
295+
296+
In earlier releases these endpoints were enabled simply by listing them under
297+
`server.endpoints`. You must now *also* set `enableUnsecureFeatures` to `true`;
298+
selecting any of them without it causes the server to refuse to start. This is
299+
deliberate — it makes enabling these powerful endpoints an explicit, considered choice.
300+
282301
=== Security Best Practices
283302

284303
1. **Keep config endpoints disabled** in production (default behavior).

tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/TikaServerConfig.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ public class TikaServerConfig {
5858
"Additionally, /config endpoints allow per-request parser configuration\n" +
5959
"which could enable dangerous operations.\n" +
6060
"Please make sure you know what you are doing.";
61+
/**
62+
* Endpoints that expose unsecure features (process-isolated pipes parsing, async
63+
* batch processing, and server status). Selecting any of these now requires
64+
* {@code enableUnsecureFeatures=true} as an explicit, deliberate opt-in.
65+
*/
66+
private static final Set<String> ENDPOINTS_REQUIRING_UNSECURE_FEATURES =
67+
new HashSet<>(Arrays.asList("pipes", "async", "status"));
6168
private static final List<String> ONLY_IN_FORK_MODE = Arrays.asList(
6269
new String[]{"maxFiles", "javaPath", "maxRestarts", "numRestarts", "forkedStatusFile", "maxForkedStartupMillis",
6370
"tmpFilePrefix"});
@@ -168,6 +175,24 @@ private void validateConsistency(Set<String> settings) throws TikaConfigExceptio
168175
if (host == null) {
169176
throw new TikaConfigException("Must specify 'host'");
170177
}
178+
if (!enableUnsecureFeatures) {
179+
List<String> requireUnsecure = new ArrayList<>();
180+
for (String endpoint : endpoints) {
181+
if (ENDPOINTS_REQUIRING_UNSECURE_FEATURES.contains(endpoint)
182+
&& !requireUnsecure.contains(endpoint)) {
183+
requireUnsecure.add(endpoint);
184+
}
185+
}
186+
if (!requireUnsecure.isEmpty()) {
187+
throw new TikaConfigException(
188+
"The following selected endpoint(s) require unsecure features to be " +
189+
"enabled: " + requireUnsecure + ". Set 'enableUnsecureFeatures' to true " +
190+
"in the 'server' section of your tika-config and confirm you understand " +
191+
"the security implications (see the tika-server documentation). These " +
192+
"endpoints were previously enabled simply by selecting them; the explicit " +
193+
"opt-in is now required.");
194+
}
195+
}
171196
}
172197

173198
public String getHost() {

tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaServerConfigTest.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import static org.junit.jupiter.api.Assertions.assertEquals;
2020
import static org.junit.jupiter.api.Assertions.assertFalse;
21+
import static org.junit.jupiter.api.Assertions.assertThrows;
2122
import static org.junit.jupiter.api.Assertions.assertTrue;
2223

2324
import java.nio.file.Path;
@@ -32,6 +33,7 @@
3233
import org.junit.jupiter.api.Test;
3334

3435
import org.apache.tika.TikaTest;
36+
import org.apache.tika.exception.TikaConfigException;
3537
import org.apache.tika.utils.ProcessUtils;
3638

3739
public class TikaServerConfigTest extends TikaTest {
@@ -76,6 +78,44 @@ public void testPorts() throws Exception {
7678
TikaServerConfig config = TikaServerConfig.load(commandLine);
7779
}
7880

81+
@Test
82+
public void testUnsecureEndpointRequiresEnableUnsecureFeatures() throws Exception {
83+
// Selecting /pipes (or /async, /status) without enableUnsecureFeatures must fail
84+
// at config load, forcing an explicit opt-in.
85+
CommandLineParser parser = new DefaultParser();
86+
Path path = getConfigPath(getClass(), "tika-config-server-pipes-no-unsecure.json");
87+
CommandLine commandLine = parser.parse(new Options()
88+
.addOption(Option
89+
.builder("c")
90+
.longOpt("config")
91+
.hasArg()
92+
.get()), new String[]{"-c", ProcessUtils.escapeCommandLine(path
93+
.toAbsolutePath()
94+
.toString())});
95+
TikaConfigException ex = assertThrows(TikaConfigException.class,
96+
() -> TikaServerConfig.load(commandLine));
97+
assertContains("enableUnsecureFeatures", ex.getMessage());
98+
assertContains("pipes", ex.getMessage());
99+
}
100+
101+
@Test
102+
public void testUnsecureEndpointAllowedWithEnableUnsecureFeatures() throws Exception {
103+
// tika-config-server-basic.json selects the 'status' endpoint together with
104+
// enableUnsecureFeatures=true, so it must load without error.
105+
CommandLineParser parser = new DefaultParser();
106+
Path path = getConfigPath(getClass(), "tika-config-server-basic.json");
107+
CommandLine commandLine = parser.parse(new Options()
108+
.addOption(Option
109+
.builder("c")
110+
.longOpt("config")
111+
.hasArg()
112+
.get()), new String[]{"-c", ProcessUtils.escapeCommandLine(path
113+
.toAbsolutePath()
114+
.toString())});
115+
TikaServerConfig config = TikaServerConfig.load(commandLine);
116+
assertTrue(config.isEnableUnsecureFeatures());
117+
}
118+
79119
@Test
80120
public void testTlsConfig() throws Exception {
81121
Set<String> settings = new HashSet<>();

tika-server/tika-server-core/src/test/resources/configs/tika-config-server-basic.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
},
99
"server": {
1010
"port": 9999,
11+
"enableUnsecureFeatures": true,
1112
"endpoints": [
1213
"rmeta",
1314
"status",

tika-server/tika-server-core/src/test/resources/configs/tika-config-server-emitter.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
},
99
"server": {
1010
"port": 9999,
11-
"enableUnsecure": true,
11+
"enableUnsecureFeatures": true,
1212
"endpoints": [
1313
"emit",
1414
"async",

tika-server/tika-server-core/src/test/resources/configs/tika-config-server-pipes-basic.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
},
99
"server": {
1010
"port": 9999,
11+
"enableUnsecureFeatures": true,
1112
"endpoints": [
1213
"rmeta",
1314
"status",

0 commit comments

Comments
 (0)