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(

Reply via email to