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 17812252de Update serialization docs (#2924)
17812252de is described below

commit 17812252de89f232abb50c8c3d4e1fe3b92d22c5
Author: Tim Allison <[email protected]>
AuthorDate: Thu Jul 2 16:53:46 2026 -0400

    Update serialization docs (#2924)
---
 .../ROOT/pages/developers/serialization.adoc       | 56 ++++++++++++++++++++++
 .../pages/migration-to-4x/design-notes-4x.adoc     | 18 ++++---
 .../pages/migration-to-4x/serialization-4x.adoc    | 24 ++++++++--
 .../tika/serialization/ComponentNameResolver.java  | 11 +++--
 4 files changed, 93 insertions(+), 16 deletions(-)

diff --git a/docs/modules/ROOT/pages/developers/serialization.adoc 
b/docs/modules/ROOT/pages/developers/serialization.adoc
index 238adf1552..84037c6a78 100644
--- a/docs/modules/ROOT/pages/developers/serialization.adoc
+++ b/docs/modules/ROOT/pages/developers/serialization.adoc
@@ -251,6 +251,62 @@ for instantiation.
 }
 ----
 
+=== Untrusted (Wire) Input: Restricted Mode
+
+Configuration files loaded at startup via `TikaLoader` are treated as trusted.
+Per-request configuration arriving over the wire — tika-server request bodies
+and pipes `FetchEmitTuple`s — is deserialized in *restricted mode*
+(`ParseContextDeserializer.readParseContext(node, true)`), which adds a second,
+fail-closed gate on top of the registry:
+
+* Only context-key types confined to shaping this request's metadata or output
+  may be instantiated from the wire: `MetadataFilter`, `ContentHandlerFactory`,
+  `ContentHandlerDecoratorFactory`, `DigesterFactory`,
+  `MetadataWriteLimiterFactory`, `UnpackSelector`
+* Types with exec/IO/network capability or control over which components run
+  are blocked: `Parser`, `Detector`, `EncodingDetector`, `Renderer`,
+  `Translator`, `EmbeddedDocumentExtractorFactory`
+* The check is fail-closed: a newly added context-key interface is blocked 
until
+  it is consciously allow-listed
+* The whole tree is scanned *before* any component is constructed
+
+The allowlist/blocklist lives in `ComponentNameResolver`
+(`WIRE_INSTANTIABLE_CONTEXT_KEYS` / `WIRE_BLOCKED_CONTEXT_KEYS`); an
+exhaustiveness test asserts every context-key interface is classified as
+exactly one of the two. Plain config DTOs (non-component keys) are never
+blocked.
+
+== Framework Directives
+
+Some JSON keys are consumed by the loading framework itself rather than by the
+component whose config object they appear in. When such a directive shares a
+JSON object with a component's own properties, it carries a leading underscore
+to avoid namespace collisions with legitimate component config keys:
+
+[source,json]
+----
+{
+  "parsers": [
+    {
+      "pdf-parser": {
+        "_mime-include": ["application/pdf"],
+        "_mime-exclude": ["application/pdf+fdf"],
+        "extractInlineImages": true
+      }
+    }
+  ]
+}
+----
+
+`_mime-include`/`_mime-exclude` are stripped before the component sees its
+config and are applied by the framework as a MIME-filtering decorator around
+the parser. New framework directives must follow the underscore convention.
+
+Marker entries that have no component-config namespace of their own are the
+exception: `"exclude"` on `default-parser`/`default-detector`/
+`default-encoding-detector` needs no prefix because those markers carry only
+framework keys.
+
 == Creating a Custom Component
 
 Complete example of a custom metadata filter:
diff --git a/docs/modules/ROOT/pages/migration-to-4x/design-notes-4x.adoc 
b/docs/modules/ROOT/pages/migration-to-4x/design-notes-4x.adoc
index d8e027d496..7913fafefb 100644
--- a/docs/modules/ROOT/pages/migration-to-4x/design-notes-4x.adoc
+++ b/docs/modules/ROOT/pages/migration-to-4x/design-notes-4x.adoc
@@ -61,16 +61,22 @@ IMPORTANT: We tried to have as few Tika dependencies in the 
plugins as possible.
 
 === Security Model
 
-Configuration files at initialization are treated as trusted sources. Runtime
-serialization/deserialization uses an allowlist of permitted packages via
-`PolymorphicObjectMapperFactory`.
-
-Custom components can add patterns to 
`META-INF/tika-serialization-allowlist.txt`.
+Configuration files at initialization are treated as trusted sources. Component
+instantiation from JSON is restricted to classes registered at compile time by
+the `@TikaComponent` annotation processor (`META-INF/tika/*.idx` files); 
unknown
+class names are rejected, and there is no Jackson default typing.
+
+Untrusted per-request configuration (tika-server requests, pipes
+`FetchEmitTuple`s) is deserialized in a restricted mode that additionally 
applies
+a fail-closed allowlist of context-key types: only metadata/output-shaping
+components (e.g. `MetadataFilter`, `ContentHandlerFactory`, `DigesterFactory`)
+may be bound from the wire; `Parser`, `Detector`, `Renderer`, and similar are
+blocked before anything is constructed. See
+xref:developers/serialization.adoc[Serialization and Configuration].
 
 === Implementation Challenges
 
 * Converted code to true Java beans with matching getters/setters
-* Used `ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE` for polymorphic 
typing
 * Replaced generic collections (`List`, `Set`) with concrete types 
(`ArrayList`, `HashSet`)
 * Converted `Path` fields to `String` due to Jackson constraints
 * Avoided Java records to enable `readerForUpdating` functionality
diff --git a/docs/modules/ROOT/pages/migration-to-4x/serialization-4x.adoc 
b/docs/modules/ROOT/pages/migration-to-4x/serialization-4x.adoc
index 8afafbe55e..4981f706bc 100644
--- a/docs/modules/ROOT/pages/migration-to-4x/serialization-4x.adoc
+++ b/docs/modules/ROOT/pages/migration-to-4x/serialization-4x.adoc
@@ -75,10 +75,18 @@ indented). Use the `--list-*-names` variants when you want 
a machine-readable ma
 
 === Custom Class Support
 
-The design permits users to add custom classes through Jackson's polymorphic 
handling:
+Custom classes are supported through the `@TikaComponent` annotation rather 
than
+Jackson polymorphic typing:
 
-* `org.apache.tika` patterns are allowed by default
-* Users can define additional inclusion patterns for security
+* Annotate the class with `@TikaComponent`; the annotation processor generates 
a
+  `META-INF/tika/*.idx` registry entry at compile time
+* Any class whose `.idx` entry is on the classpath can be referenced by its
+  friendly name in JSON configuration
+* Class names or packages that are not registered cannot be instantiated from
+  JSON — there is no package-pattern allowlist and no `Class.forName` fallback
+
+See xref:developers/serialization.adoc[Serialization and Configuration] for the
+full mechanism.
 
 === Configuration Consistency
 
@@ -137,7 +145,13 @@ dependencies on components like `PDFParser`.
 == Security Considerations
 
 * Configuration files at initialization are treated as trusted sources
-* Runtime serialization/deserialization uses an allowlist of permitted packages
-* Custom components can register patterns in 
`META-INF/tika-serialization-allowlist.txt`
+* Only classes registered via `@TikaComponent` (compile-time-generated
+  `META-INF/tika/*.idx` files) can be instantiated from JSON; unregistered 
class
+  names are rejected and there is no Jackson default typing
+* Untrusted per-request configuration (tika-server requests, pipes
+  `FetchEmitTuple`s) is deserialized in restricted mode: a fail-closed 
allowlist
+  permits only metadata/output-shaping context keys (e.g. `MetadataFilter`,
+  `ContentHandlerFactory`, `DigesterFactory`) and blocks `Parser`, `Detector`,
+  `Renderer`, and similar before anything is constructed
 
 See link:design-notes-4x.html[Design Notes for 4.x] for additional 
architectural context.
diff --git 
a/tika-serialization/src/main/java/org/apache/tika/serialization/ComponentNameResolver.java
 
b/tika-serialization/src/main/java/org/apache/tika/serialization/ComponentNameResolver.java
index 977dd895a4..7b3db573c3 100644
--- 
a/tika-serialization/src/main/java/org/apache/tika/serialization/ComponentNameResolver.java
+++ 
b/tika-serialization/src/main/java/org/apache/tika/serialization/ComponentNameResolver.java
@@ -128,13 +128,14 @@ public final class ComponentNameResolver {
     }
 
     /**
-     * Resolves a friendly name or FQCN to a Class.
-     * Searches all registered component registries, falling back to 
Class.forName.
+     * Resolves a friendly name (or registered FQCN) to a Class by searching 
the
+     * registered component registries only. There is deliberately no
+     * Class.forName fallback: unregistered names are rejected for security.
      *
-     * @param name friendly name or fully qualified class name
-     * @param classLoader the class loader to use for FQCN fallback
+     * @param name friendly name or registered fully qualified class name
+     * @param classLoader unused for resolution; retained for API stability
      * @return the resolved class
-     * @throws ClassNotFoundException if not found in any registry and not a 
valid FQCN
+     * @throws ClassNotFoundException if the name is not in any registry
      */
     public static Class<?> resolveClass(String name, ClassLoader classLoader)
             throws ClassNotFoundException {

Reply via email to