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 4847f78c8f refuse wire-blocked component names given as bare strings
(#3351)
4847f78c8f is described below
commit 4847f78c8faa5b4f51ecb45a29290be28e59b365
Author: Naveed <[email protected]>
AuthorDate: Fri Oct 16 23:47:37 2026 +0530
refuse wire-blocked component names given as bare strings (#3351)
scanForBlocked only checked object keys, so a request parseContext of
{"metadata-filters":["openai-embedding-filter"]} passed the gate and
resolved to a working embedding filter bound into the request.
Generated-by: Claude Code (Claude Opus 5.5)
---
.../serialization/serdes/ParseContextDeserializer.java | 16 +++++++++++-----
.../serialization/WireRestrictedParseContextTest.java | 12 ++++++++++++
.../apache/tika/server/standard/TikaResourceTest.java | 6 ++++++
3 files changed, 29 insertions(+), 5 deletions(-)
diff --git
a/tika-serialization/src/main/java/org/apache/tika/serialization/serdes/ParseContextDeserializer.java
b/tika-serialization/src/main/java/org/apache/tika/serialization/serdes/ParseContextDeserializer.java
index 2ac419eb95..b5bfe5dfc4 100644
---
a/tika-serialization/src/main/java/org/apache/tika/serialization/serdes/ParseContextDeserializer.java
+++
b/tika-serialization/src/main/java/org/apache/tika/serialization/serdes/ParseContextDeserializer.java
@@ -167,9 +167,10 @@ public class ParseContextDeserializer extends
JsonDeserializer<ParseContext> {
* position-aware: a top-level flat key for a self-configuring component
(e.g.
* {@code {"pdf-parser":{...}}}) is an inert per-request config that
resolveAll skips, so it is
* allowed and its opaque config subtree is not scanned; every other key
is checked and its
- * subtree scanned, refusing any blocked object key at any depth.
Bare-string references are not
- * scanned -- they name a defaults instance with no config. Running before
resolution matters
- * because merely constructing a blocked component can have side effects.
+ * subtree scanned, refusing any blocked object key at any depth.
Bare-string references are
+ * checked only against the wire-blocked names -- they name a defaults
instance with no config.
+ * Running before resolution matters because merely constructing a blocked
component can have
+ * side effects.
*/
private static void assertNoBlockedComponents(JsonNode contextNode) throws
IOException {
if (contextNode == null || !contextNode.isObject()) {
@@ -189,8 +190,9 @@ public class ParseContextDeserializer extends
JsonDeserializer<ParseContext> {
}
/**
- * Recursively refuses blocked-component object keys within a scanned
subtree. Only object keys
- * are checked; bare strings are inert defaults (see {@link
#assertNoBlockedComponents}).
+ * Recursively refuses blocked-component object keys within a scanned
subtree, and bare strings
+ * naming a wire-blocked component: its type is allowed, so the defaults
instance is bound and
+ * run like the object form.
*/
private static void scanForBlocked(JsonNode node) throws IOException {
if (node == null) {
@@ -207,6 +209,10 @@ public class ParseContextDeserializer extends
JsonDeserializer<ParseContext> {
for (JsonNode child : node) {
scanForBlocked(child);
}
+ } else if (node.isTextual() &&
ComponentNameResolver.isWireBlockedName(node.asText())) {
+ throw new IOException("Component '" + node.asText() + "' may not
be supplied via a "
+ + "request parseContext. It must be configured server-side
in the Tika config, "
+ + "not at request time.");
}
}
diff --git
a/tika-serialization/src/test/java/org/apache/tika/serialization/WireRestrictedParseContextTest.java
b/tika-serialization/src/test/java/org/apache/tika/serialization/WireRestrictedParseContextTest.java
index 8d5a41864d..6b213e29cc 100644
---
a/tika-serialization/src/test/java/org/apache/tika/serialization/WireRestrictedParseContextTest.java
+++
b/tika-serialization/src/test/java/org/apache/tika/serialization/WireRestrictedParseContextTest.java
@@ -157,6 +157,18 @@ public class WireRestrictedParseContextTest {
assertDoesNotThrow(() -> restrictedMapper().readValue(json,
ParseContext.class));
}
+ @Test
+ public void restrictedRejectsBareStringWireBlockedName() {
+ // the bare-string form still binds a working defaults instance of an
allowed type
+ for (String name : new String[]{"openai-embedding-filter",
"jina-embedding-filter"}) {
+ String json = "{\"metadata-filters\":[\"" + name + "\"]}";
+ Exception e = assertThrows(Exception.class,
+ () -> restrictedMapper().readValue(json,
ParseContext.class), name);
+ assertTrue(rootMessage(e).contains("may not be supplied via a
request parseContext"),
+ name + ": expected wire-blocked rejection, got: " +
rootMessage(e));
+ }
+ }
+
@Test
public void restrictedRejectsParserSmuggledInArrayConfig() {
// Nesting a parser inside an array config (e.g. metadata-filters)
must also be refused.
diff --git
a/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/TikaResourceTest.java
b/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/TikaResourceTest.java
index 7414e7cd77..86a9155453 100644
---
a/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/TikaResourceTest.java
+++
b/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/TikaResourceTest.java
@@ -443,6 +443,12 @@ public class TikaResourceTest extends CXFTestBase {
name);
assertTrue(rootMessage(e).contains("may not be supplied via a
request parseContext"),
name + ": expected wire-blocked rejection, got: " +
rootMessage(e));
+ String bareJson = "{\"metadata-filters\":[\"" + name + "\"]}";
+ e = assertThrows(Exception.class,
+ () -> TikaResource.mergeParseContextFromConfig(bareJson,
new ParseContext()),
+ name);
+ assertTrue(rootMessage(e).contains("may not be supplied via a
request parseContext"),
+ name + ": expected wire-blocked rejection, got: " +
rootMessage(e));
}
// the flat per-request config tunes the loaded filter and stays
allowed
assertDoesNotThrow(() -> TikaResource.mergeParseContextFromConfig(