This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 998a60666f72 CAMEL-24725: apply the shared deserialization filter in 
KeyValueRepositoryHelper
998a60666f72 is described below

commit 998a60666f72e53d62b51c5cab249f3be00ed860
Author: Andrea Cosentino <[email protected]>
AuthorDate: Tue Sep 15 06:51:46 2026 +0200

    CAMEL-24725: apply the shared deserialization filter in 
KeyValueRepositoryHelper
    
    KeyValueRepositoryHelper (new in 4.23, CAMEL-24463) deserialized stored 
values with a
    plain ObjectInputStream and no JEP-290 ObjectInputFilter, unlike every other
    ObjectInputStream call site in Camel which goes through 
DeserializationFilterHelper.
    
    All deserialize(...) overloads now resolve a filter through
    DeserializationFilterHelper (explicit pattern, then jdk.serialFilter, then 
the
    conservative Camel default), and filter-accepting overloads let callers 
pass a
    configured pattern. The persistent backends (cassandraql, hazelcast, 
infinispan, jpa,
    kafka, redis, sql) expose a `deserializationFilter` option so applications 
storing
    their own Serializable classes can widen the allow-list. In-memory backends 
are
    unaffected. The key-value-repository docs gain a Serialization section.
    
    main only: the helper has not shipped in a release.
    
    Closes #26443
    
    Co-Authored-By: Claude Opus 5 <[email protected]>
---
 .../catalog/beans/CassandraKeyValueRepository.json |  2 +-
 .../catalog/beans/HazelcastKeyValueRepository.json |  2 +-
 .../beans/InfinispanRemoteKeyValueRepository.json  |  2 +-
 .../catalog/beans/JdbcKeyValueRepository.json      |  2 +-
 .../camel/catalog/beans/JpaKeyValueRepository.json |  2 +-
 .../catalog/beans/KafkaKeyValueRepository.json     |  2 +-
 .../catalog/beans/RedisKeyValueRepository.json     |  2 +-
 .../CassandraKeyValueRepositoryConfigurer.java     |  6 ++
 .../camel/bean/CassandraKeyValueRepository.json    |  2 +-
 .../cassandra/CassandraKeyValueRepository.java     | 25 ++++++-
 .../HazelcastKeyValueRepositoryConfigurer.java     |  6 ++
 .../camel/bean/HazelcastKeyValueRepository.json    |  2 +-
 .../hazelcast/HazelcastKeyValueRepository.java     | 29 +++++++-
 ...finispanRemoteKeyValueRepositoryConfigurer.java |  6 ++
 .../bean/InfinispanRemoteKeyValueRepository.json   |  2 +-
 .../remote/InfinispanRemoteKeyValueRepository.java | 33 +++++++--
 .../jpa/JpaKeyValueRepositoryConfigurer.java       |  6 ++
 .../apache/camel/bean/JpaKeyValueRepository.json   |  2 +-
 .../keyvalue/jpa/JpaKeyValueRepository.java        | 32 ++++++--
 .../kafka/KafkaKeyValueRepositoryConfigurer.java   |  6 ++
 .../apache/camel/bean/KafkaKeyValueRepository.json |  2 +-
 .../keyvalue/kafka/KafkaKeyValueRepository.java    | 23 +++++-
 .../redis/RedisKeyValueRepositoryConfigurer.java   |  6 ++
 .../apache/camel/bean/RedisKeyValueRepository.json |  2 +-
 .../component/redis/RedisKeyValueRepository.java   | 29 +++++++-
 .../jdbc/JdbcKeyValueRepositoryConfigurer.java     |  6 ++
 .../apache/camel/bean/JdbcKeyValueRepository.json  |  2 +-
 .../keyvalue/jdbc/JdbcKeyValueRepository.java      | 23 +++++-
 .../camel/support/KeyValueRepositoryHelper.java    | 85 ++++++++++++++++++----
 .../support/KeyValueRepositoryHelperTest.java      | 74 +++++++++++++++++++
 .../modules/ROOT/pages/key-value-repository.adoc   | 35 +++++++++
 31 files changed, 406 insertions(+), 52 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/CassandraKeyValueRepository.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/CassandraKeyValueRepository.json
index 56c9f95199d2..67355e21c3d3 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/CassandraKeyValueRepository.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/CassandraKeyValueRepository.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-cassandraql",
     "version": "4.23.0-SNAPSHOT",
-    "properties": { "session": { "index": 0, "kind": "property", 
"displayName": "Session", "required": true, "type": "object", "javaType": 
"org.apache.camel.utils.cassandra.CassandraSessionHolder", "deprecated": false, 
"autowired": false, "secret": false, "description": "Cassandra session" }, 
"table": { "index": 1, "kind": "property", "displayName": "Table", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "def [...]
+    "properties": { "session": { "index": 0, "kind": "property", 
"displayName": "Session", "required": true, "type": "object", "javaType": 
"org.apache.camel.utils.cassandra.CassandraSessionHolder", "deprecated": false, 
"autowired": false, "secret": false, "description": "Cassandra session" }, 
"table": { "index": 1, "kind": "property", "displayName": "Table", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "def [...]
   }
 }
 
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/HazelcastKeyValueRepository.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/HazelcastKeyValueRepository.json
index 22d363a3f59c..6edaa0c3c058 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/HazelcastKeyValueRepository.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/HazelcastKeyValueRepository.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-hazelcast",
     "version": "4.23.0-SNAPSHOT",
-    "properties": { "mapName": { "index": 0, "kind": "property", 
"displayName": "Map Name", "required": false, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "HazelcastKeyValueRepository", "description": "Name of the 
Hazelcast map to use" }, "hazelcastInstance": { "index": 1, "kind": "property", 
"displayName": "Hazelcast Instance", "required": false, "type": "object", 
"javaType": "com.hazelcast.core.HazelcastIns [...]
+    "properties": { "mapName": { "index": 0, "kind": "property", 
"displayName": "Map Name", "required": false, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "HazelcastKeyValueRepository", "description": "Name of the 
Hazelcast map to use" }, "hazelcastInstance": { "index": 1, "kind": "property", 
"displayName": "Hazelcast Instance", "required": false, "type": "object", 
"javaType": "com.hazelcast.core.HazelcastIns [...]
   }
 }
 
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/InfinispanRemoteKeyValueRepository.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/InfinispanRemoteKeyValueRepository.json
index 7a920e4f70b2..bce4c304e5c1 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/InfinispanRemoteKeyValueRepository.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/InfinispanRemoteKeyValueRepository.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-infinispan",
     "version": "4.23.0-SNAPSHOT",
-    "properties": { "cacheName": { "index": 0, "kind": "property", 
"displayName": "Cache Name", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "autowired": false, "secret": false, 
"description": "Name of cache" }, "configuration": { "index": 1, "kind": 
"property", "displayName": "Configuration", "required": false, "type": 
"object", "javaType": 
"org.apache.camel.component.infinispan.remote.InfinispanRemoteConfiguration", 
"deprecated": false, "auto [...]
+    "properties": { "cacheName": { "index": 0, "kind": "property", 
"displayName": "Cache Name", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "autowired": false, "secret": false, 
"description": "Name of cache" }, "configuration": { "index": 1, "kind": 
"property", "displayName": "Configuration", "required": false, "type": 
"object", "javaType": 
"org.apache.camel.component.infinispan.remote.InfinispanRemoteConfiguration", 
"deprecated": false, "auto [...]
   }
 }
 
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/JdbcKeyValueRepository.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/JdbcKeyValueRepository.json
index 07bc8667d665..2042d4a6633e 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/JdbcKeyValueRepository.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/JdbcKeyValueRepository.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-sql",
     "version": "4.23.0-SNAPSHOT",
-    "properties": { "jdbcTemplate": { "index": 0, "kind": "property", 
"displayName": "Jdbc Template", "required": true, "type": "object", "javaType": 
"org.springframework.jdbc.core.JdbcTemplate", "deprecated": false, "autowired": 
false, "secret": false, "description": "The Spring JdbcTemplate to use for 
connecting to the database" }, "transactionTemplate": { "index": 1, "kind": 
"property", "displayName": "Transaction Template", "required": true, "type": 
"object", "javaType": "org.springf [...]
+    "properties": { "jdbcTemplate": { "index": 0, "kind": "property", 
"displayName": "Jdbc Template", "required": true, "type": "object", "javaType": 
"org.springframework.jdbc.core.JdbcTemplate", "deprecated": false, "autowired": 
false, "secret": false, "description": "The Spring JdbcTemplate to use for 
connecting to the database" }, "transactionTemplate": { "index": 1, "kind": 
"property", "displayName": "Transaction Template", "required": true, "type": 
"object", "javaType": "org.springf [...]
   }
 }
 
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/JpaKeyValueRepository.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/JpaKeyValueRepository.json
index 2ec1140fe36b..6073d5e78960 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/JpaKeyValueRepository.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/JpaKeyValueRepository.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-jpa",
     "version": "4.23.0-SNAPSHOT",
-    "properties": { "entityManagerFactory": { "index": 0, "kind": "property", 
"displayName": "Entity Manager Factory", "required": true, "type": "object", 
"javaType": "jakarta.persistence.EntityManagerFactory", "deprecated": false, 
"autowired": false, "secret": false, "description": "The JPA 
EntityManagerFactory to use" }, "transactionStrategy": { "index": 1, "kind": 
"property", "displayName": "Transaction Strategy", "required": false, "type": 
"object", "javaType": "org.apache.camel.comp [...]
+    "properties": { "entityManagerFactory": { "index": 0, "kind": "property", 
"displayName": "Entity Manager Factory", "required": true, "type": "object", 
"javaType": "jakarta.persistence.EntityManagerFactory", "deprecated": false, 
"autowired": false, "secret": false, "description": "The JPA 
EntityManagerFactory to use" }, "transactionStrategy": { "index": 1, "kind": 
"property", "displayName": "Transaction Strategy", "required": false, "type": 
"object", "javaType": "org.apache.camel.comp [...]
   }
 }
 
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/KafkaKeyValueRepository.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/KafkaKeyValueRepository.json
index dd228413c88e..d7c3d1900b55 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/KafkaKeyValueRepository.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/KafkaKeyValueRepository.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-kafka",
     "version": "4.23.0-SNAPSHOT",
-    "properties": { "consumerConfig": { "index": 0, "kind": "property", 
"displayName": "Consumer Config", "required": false, "type": "object", 
"javaType": "java.util.Properties", "deprecated": false, "autowired": false, 
"secret": false, "description": "Custom properties for the Kafka consumer" }, 
"producerConfig": { "index": 1, "kind": "property", "displayName": "Producer 
Config", "required": false, "type": "object", "javaType": 
"java.util.Properties", "deprecated": false, "autowired": f [...]
+    "properties": { "consumerConfig": { "index": 0, "kind": "property", 
"displayName": "Consumer Config", "required": false, "type": "object", 
"javaType": "java.util.Properties", "deprecated": false, "autowired": false, 
"secret": false, "description": "Custom properties for the Kafka consumer" }, 
"producerConfig": { "index": 1, "kind": "property", "displayName": "Producer 
Config", "required": false, "type": "object", "javaType": 
"java.util.Properties", "deprecated": false, "autowired": f [...]
   }
 }
 
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/RedisKeyValueRepository.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/RedisKeyValueRepository.json
index 35fad0e6c77f..c8fc56830883 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/RedisKeyValueRepository.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/RedisKeyValueRepository.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-redis",
     "version": "4.23.0-SNAPSHOT",
-    "properties": { "redisson": { "index": 0, "kind": "property", 
"displayName": "Redisson", "label": "advanced", "required": false, "type": 
"object", "javaType": "org.redisson.api.RedissonClient", "deprecated": false, 
"autowired": false, "secret": false, "description": "To use an existing 
Redisson client to connect to Redis server" }, "endpoint": { "index": 1, 
"kind": "property", "displayName": "Endpoint", "required": true, "type": 
"string", "javaType": "java.lang.String", "deprecated": [...]
+    "properties": { "redisson": { "index": 0, "kind": "property", 
"displayName": "Redisson", "label": "advanced", "required": false, "type": 
"object", "javaType": "org.redisson.api.RedissonClient", "deprecated": false, 
"autowired": false, "secret": false, "description": "To use an existing 
Redisson client to connect to Redis server" }, "endpoint": { "index": 1, 
"kind": "property", "displayName": "Endpoint", "required": true, "type": 
"string", "javaType": "java.lang.String", "deprecated": [...]
   }
 }
 
diff --git 
a/components/camel-cassandraql/src/generated/java/org/apache/camel/processor/keyvalue/cassandra/CassandraKeyValueRepositoryConfigurer.java
 
b/components/camel-cassandraql/src/generated/java/org/apache/camel/processor/keyvalue/cassandra/CassandraKeyValueRepositoryConfigurer.java
index 88dceac9d741..761ea0924963 100644
--- 
a/components/camel-cassandraql/src/generated/java/org/apache/camel/processor/keyvalue/cassandra/CassandraKeyValueRepositoryConfigurer.java
+++ 
b/components/camel-cassandraql/src/generated/java/org/apache/camel/processor/keyvalue/cassandra/CassandraKeyValueRepositoryConfigurer.java
@@ -23,6 +23,8 @@ public class CassandraKeyValueRepositoryConfigurer extends 
org.apache.camel.supp
     public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
         
org.apache.camel.processor.keyvalue.cassandra.CassandraKeyValueRepository 
target = 
(org.apache.camel.processor.keyvalue.cassandra.CassandraKeyValueRepository) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "deserializationfilter":
+        case "deserializationFilter": 
target.setDeserializationFilter(property(camelContext, java.lang.String.class, 
value)); return true;
         case "readconsistencylevel":
         case "readConsistencyLevel": 
target.setReadConsistencyLevel(property(camelContext, 
com.datastax.oss.driver.api.core.ConsistencyLevel.class, value)); return true;
         case "session": target.setSession(property(camelContext, 
com.datastax.oss.driver.api.core.CqlSession.class, value)); return true;
@@ -36,6 +38,8 @@ public class CassandraKeyValueRepositoryConfigurer extends 
org.apache.camel.supp
     @Override
     public Class<?> getOptionType(String name, boolean ignoreCase) {
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "deserializationfilter":
+        case "deserializationFilter": return java.lang.String.class;
         case "readconsistencylevel":
         case "readConsistencyLevel": return 
com.datastax.oss.driver.api.core.ConsistencyLevel.class;
         case "session": return 
com.datastax.oss.driver.api.core.CqlSession.class;
@@ -50,6 +54,8 @@ public class CassandraKeyValueRepositoryConfigurer extends 
org.apache.camel.supp
     public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
         
org.apache.camel.processor.keyvalue.cassandra.CassandraKeyValueRepository 
target = 
(org.apache.camel.processor.keyvalue.cassandra.CassandraKeyValueRepository) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "deserializationfilter":
+        case "deserializationFilter": return target.getDeserializationFilter();
         case "readconsistencylevel":
         case "readConsistencyLevel": return target.getReadConsistencyLevel();
         case "session": return target.getSession();
diff --git 
a/components/camel-cassandraql/src/generated/resources/META-INF/services/org/apache/camel/bean/CassandraKeyValueRepository.json
 
b/components/camel-cassandraql/src/generated/resources/META-INF/services/org/apache/camel/bean/CassandraKeyValueRepository.json
index 56c9f95199d2..67355e21c3d3 100644
--- 
a/components/camel-cassandraql/src/generated/resources/META-INF/services/org/apache/camel/bean/CassandraKeyValueRepository.json
+++ 
b/components/camel-cassandraql/src/generated/resources/META-INF/services/org/apache/camel/bean/CassandraKeyValueRepository.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-cassandraql",
     "version": "4.23.0-SNAPSHOT",
-    "properties": { "session": { "index": 0, "kind": "property", 
"displayName": "Session", "required": true, "type": "object", "javaType": 
"org.apache.camel.utils.cassandra.CassandraSessionHolder", "deprecated": false, 
"autowired": false, "secret": false, "description": "Cassandra session" }, 
"table": { "index": 1, "kind": "property", "displayName": "Table", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "def [...]
+    "properties": { "session": { "index": 0, "kind": "property", 
"displayName": "Session", "required": true, "type": "object", "javaType": 
"org.apache.camel.utils.cassandra.CassandraSessionHolder", "deprecated": false, 
"autowired": false, "secret": false, "description": "Cassandra session" }, 
"table": { "index": 1, "kind": "property", "displayName": "Table", "required": 
false, "type": "string", "javaType": "java.lang.String", "deprecated": false, 
"autowired": false, "secret": false, "def [...]
   }
 }
 
diff --git 
a/components/camel-cassandraql/src/main/java/org/apache/camel/processor/keyvalue/cassandra/CassandraKeyValueRepository.java
 
b/components/camel-cassandraql/src/main/java/org/apache/camel/processor/keyvalue/cassandra/CassandraKeyValueRepository.java
index 74136447a9d4..0e4089591ba7 100644
--- 
a/components/camel-cassandraql/src/main/java/org/apache/camel/processor/keyvalue/cassandra/CassandraKeyValueRepository.java
+++ 
b/components/camel-cassandraql/src/main/java/org/apache/camel/processor/keyvalue/cassandra/CassandraKeyValueRepository.java
@@ -95,6 +95,13 @@ public class CassandraKeyValueRepository extends 
ServiceSupport implements KeyVa
     @Metadata(description = "Read consistency level",
               enums = 
"ANY,ONE,TWO,THREE,QUORUM,ALL,LOCAL_ONE,LOCAL_QUORUM,EACH_QUORUM,SERIAL,LOCAL_SERIAL")
     private ConsistencyLevel readConsistencyLevel;
+    @Metadata(label = "advanced,security",
+              description = "Sets an ObjectInputFilter pattern 
(jdk.serialFilter syntax) applied when deserializing"
+                            + " values read back from the repository. When not 
set, the JVM-wide jdk.serialFilter is"
+                            + " used if present; otherwise a conservative 
default filter denying java.net.* and"
+                            + " otherwise allowing java.*, javax.* and 
org.apache.camel.* packages is applied. Widen"
+                            + " this pattern when storing instances of your 
own classes in the repository.")
+    private String deserializationFilter;
 
     private PreparedStatement insertStatement;
     private PreparedStatement insertWithTtlStatement;
@@ -280,7 +287,7 @@ public class CassandraKeyValueRepository extends 
ServiceSupport implements KeyVa
             return null;
         }
         ByteBuffer buffer = row.getByteBuffer(VALUE_COLUMN);
-        return buffer != null ? KeyValueRepositoryHelper.deserialize(buffer) : 
null;
+        return buffer != null ? KeyValueRepositoryHelper.deserialize(buffer, 
deserializationFilter) : null;
     }
 
     /**
@@ -368,7 +375,7 @@ public class CassandraKeyValueRepository extends 
ServiceSupport implements KeyVa
         }
         // Insert was not applied; return the existing value from the result 
row
         ByteBuffer existingBuffer = row.getByteBuffer(VALUE_COLUMN);
-        return existingBuffer != null ? 
KeyValueRepositoryHelper.deserialize(existingBuffer) : null;
+        return existingBuffer != null ? 
KeyValueRepositoryHelper.deserialize(existingBuffer, deserializationFilter) : 
null;
     }
 
     /**
@@ -476,4 +483,18 @@ public class CassandraKeyValueRepository extends 
ServiceSupport implements KeyVa
     public void setReadConsistencyLevel(ConsistencyLevel readConsistencyLevel) 
{
         this.readConsistencyLevel = readConsistencyLevel;
     }
+
+    public String getDeserializationFilter() {
+        return deserializationFilter;
+    }
+
+    /**
+     * Sets an {@link java.io.ObjectInputFilter} pattern (same syntax as 
{@code jdk.serialFilter}) applied when
+     * deserializing values read back from the repository. When not set, the 
JVM-wide {@code jdk.serialFilter} is used
+     * if present, otherwise a conservative default filter is applied. Widen 
this pattern when storing instances of your
+     * own classes in the repository.
+     */
+    public void setDeserializationFilter(String deserializationFilter) {
+        this.deserializationFilter = deserializationFilter;
+    }
 }
diff --git 
a/components/camel-hazelcast/src/generated/java/org/apache/camel/component/hazelcast/HazelcastKeyValueRepositoryConfigurer.java
 
b/components/camel-hazelcast/src/generated/java/org/apache/camel/component/hazelcast/HazelcastKeyValueRepositoryConfigurer.java
index d2b8190ec5d7..f0ad0320361f 100644
--- 
a/components/camel-hazelcast/src/generated/java/org/apache/camel/component/hazelcast/HazelcastKeyValueRepositoryConfigurer.java
+++ 
b/components/camel-hazelcast/src/generated/java/org/apache/camel/component/hazelcast/HazelcastKeyValueRepositoryConfigurer.java
@@ -23,6 +23,8 @@ public class HazelcastKeyValueRepositoryConfigurer extends 
org.apache.camel.supp
     public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
         org.apache.camel.component.hazelcast.HazelcastKeyValueRepository 
target = (org.apache.camel.component.hazelcast.HazelcastKeyValueRepository) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "deserializationfilter":
+        case "deserializationFilter": 
target.setDeserializationFilter(property(camelContext, java.lang.String.class, 
value)); return true;
         case "hazelcastinstance":
         case "hazelcastInstance": 
target.setHazelcastInstance(property(camelContext, 
com.hazelcast.core.HazelcastInstance.class, value)); return true;
         case "mapname":
@@ -34,6 +36,8 @@ public class HazelcastKeyValueRepositoryConfigurer extends 
org.apache.camel.supp
     @Override
     public Class<?> getOptionType(String name, boolean ignoreCase) {
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "deserializationfilter":
+        case "deserializationFilter": return java.lang.String.class;
         case "hazelcastinstance":
         case "hazelcastInstance": return 
com.hazelcast.core.HazelcastInstance.class;
         case "mapname":
@@ -46,6 +50,8 @@ public class HazelcastKeyValueRepositoryConfigurer extends 
org.apache.camel.supp
     public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
         org.apache.camel.component.hazelcast.HazelcastKeyValueRepository 
target = (org.apache.camel.component.hazelcast.HazelcastKeyValueRepository) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "deserializationfilter":
+        case "deserializationFilter": return target.getDeserializationFilter();
         case "hazelcastinstance":
         case "hazelcastInstance": return target.getHazelcastInstance();
         case "mapname":
diff --git 
a/components/camel-hazelcast/src/generated/resources/META-INF/services/org/apache/camel/bean/HazelcastKeyValueRepository.json
 
b/components/camel-hazelcast/src/generated/resources/META-INF/services/org/apache/camel/bean/HazelcastKeyValueRepository.json
index 22d363a3f59c..6edaa0c3c058 100644
--- 
a/components/camel-hazelcast/src/generated/resources/META-INF/services/org/apache/camel/bean/HazelcastKeyValueRepository.json
+++ 
b/components/camel-hazelcast/src/generated/resources/META-INF/services/org/apache/camel/bean/HazelcastKeyValueRepository.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-hazelcast",
     "version": "4.23.0-SNAPSHOT",
-    "properties": { "mapName": { "index": 0, "kind": "property", 
"displayName": "Map Name", "required": false, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "HazelcastKeyValueRepository", "description": "Name of the 
Hazelcast map to use" }, "hazelcastInstance": { "index": 1, "kind": "property", 
"displayName": "Hazelcast Instance", "required": false, "type": "object", 
"javaType": "com.hazelcast.core.HazelcastIns [...]
+    "properties": { "mapName": { "index": 0, "kind": "property", 
"displayName": "Map Name", "required": false, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "HazelcastKeyValueRepository", "description": "Name of the 
Hazelcast map to use" }, "hazelcastInstance": { "index": 1, "kind": "property", 
"displayName": "Hazelcast Instance", "required": false, "type": "object", 
"javaType": "com.hazelcast.core.HazelcastIns [...]
   }
 }
 
diff --git 
a/components/camel-hazelcast/src/main/java/org/apache/camel/component/hazelcast/HazelcastKeyValueRepository.java
 
b/components/camel-hazelcast/src/main/java/org/apache/camel/component/hazelcast/HazelcastKeyValueRepository.java
index fd8df970d4da..cc4de61d08ba 100644
--- 
a/components/camel-hazelcast/src/main/java/org/apache/camel/component/hazelcast/HazelcastKeyValueRepository.java
+++ 
b/components/camel-hazelcast/src/main/java/org/apache/camel/component/hazelcast/HazelcastKeyValueRepository.java
@@ -70,6 +70,13 @@ public class HazelcastKeyValueRepository extends 
ServiceSupport implements KeyVa
 
     @Metadata(description = "To use an existing Hazelcast instance instead of 
creating a local one")
     private HazelcastInstance hazelcastInstance;
+    @Metadata(label = "advanced,security",
+              description = "Sets an ObjectInputFilter pattern 
(jdk.serialFilter syntax) applied when deserializing"
+                            + " values read back from the repository. When not 
set, the JVM-wide jdk.serialFilter is"
+                            + " used if present; otherwise a conservative 
default filter denying java.net.* and"
+                            + " otherwise allowing java.*, javax.* and 
org.apache.camel.* packages is applied. Widen"
+                            + " this pattern when storing instances of your 
own classes in the repository.")
+    private String deserializationFilter;
 
     /**
      * Creates a new Hazelcast-backed key-value repository with default 
settings (local instance, default map name).
@@ -109,11 +116,25 @@ public class HazelcastKeyValueRepository extends 
ServiceSupport implements KeyVa
         this.hazelcastInstance = hazelcastInstance;
     }
 
+    public String getDeserializationFilter() {
+        return deserializationFilter;
+    }
+
+    /**
+     * Sets an {@link java.io.ObjectInputFilter} pattern (same syntax as 
{@code jdk.serialFilter}) applied when
+     * deserializing values read back from the repository. When not set, the 
JVM-wide {@code jdk.serialFilter} is used
+     * if present, otherwise a conservative default filter is applied. Widen 
this pattern when storing instances of your
+     * own classes in the repository.
+     */
+    public void setDeserializationFilter(String deserializationFilter) {
+        this.deserializationFilter = deserializationFilter;
+    }
+
     @Override
     @ManagedOperation(description = "Get value by key")
     public Object get(String key) {
         byte[] bytes = map.get(key);
-        return bytes != null ? KeyValueRepositoryHelper.deserialize(bytes) : 
null;
+        return bytes != null ? KeyValueRepositoryHelper.deserialize(bytes, 
deserializationFilter) : null;
     }
 
     @Override
@@ -126,14 +147,14 @@ public class HazelcastKeyValueRepository extends 
ServiceSupport implements KeyVa
         } else {
             previous = map.put(key, serialized);
         }
-        return previous != null ? 
KeyValueRepositoryHelper.deserialize(previous) : null;
+        return previous != null ? 
KeyValueRepositoryHelper.deserialize(previous, deserializationFilter) : null;
     }
 
     @Override
     @ManagedOperation(description = "Delete a key")
     public Object delete(String key) {
         byte[] bytes = map.remove(key);
-        return bytes != null ? KeyValueRepositoryHelper.deserialize(bytes) : 
null;
+        return bytes != null ? KeyValueRepositoryHelper.deserialize(bytes, 
deserializationFilter) : null;
     }
 
     @Override
@@ -162,7 +183,7 @@ public class HazelcastKeyValueRepository extends 
ServiceSupport implements KeyVa
         } else {
             existing = map.putIfAbsent(key, serialized);
         }
-        return existing != null ? 
KeyValueRepositoryHelper.deserialize(existing) : null;
+        return existing != null ? 
KeyValueRepositoryHelper.deserialize(existing, deserializationFilter) : null;
     }
 
     @Override
diff --git 
a/components/camel-infinispan/camel-infinispan/src/generated/java/org/apache/camel/component/infinispan/remote/InfinispanRemoteKeyValueRepositoryConfigurer.java
 
b/components/camel-infinispan/camel-infinispan/src/generated/java/org/apache/camel/component/infinispan/remote/InfinispanRemoteKeyValueRepositoryConfigurer.java
index 74a1b158fff4..f1571e15ae48 100644
--- 
a/components/camel-infinispan/camel-infinispan/src/generated/java/org/apache/camel/component/infinispan/remote/InfinispanRemoteKeyValueRepositoryConfigurer.java
+++ 
b/components/camel-infinispan/camel-infinispan/src/generated/java/org/apache/camel/component/infinispan/remote/InfinispanRemoteKeyValueRepositoryConfigurer.java
@@ -28,6 +28,8 @@ public class InfinispanRemoteKeyValueRepositoryConfigurer 
extends org.apache.cam
         case "cachename":
         case "cacheName": target.setCacheName(property(camelContext, 
java.lang.String.class, value)); return true;
         case "configuration": target.setConfiguration(property(camelContext, 
org.apache.camel.component.infinispan.remote.InfinispanRemoteConfiguration.class,
 value)); return true;
+        case "deserializationfilter":
+        case "deserializationFilter": 
target.setDeserializationFilter(property(camelContext, java.lang.String.class, 
value)); return true;
         default: return false;
         }
     }
@@ -40,6 +42,8 @@ public class InfinispanRemoteKeyValueRepositoryConfigurer 
extends org.apache.cam
         case "cachename":
         case "cacheName": return java.lang.String.class;
         case "configuration": return 
org.apache.camel.component.infinispan.remote.InfinispanRemoteConfiguration.class;
+        case "deserializationfilter":
+        case "deserializationFilter": return java.lang.String.class;
         default: return null;
         }
     }
@@ -53,6 +57,8 @@ public class InfinispanRemoteKeyValueRepositoryConfigurer 
extends org.apache.cam
         case "cachename":
         case "cacheName": return target.getCacheName();
         case "configuration": return target.getConfiguration();
+        case "deserializationfilter":
+        case "deserializationFilter": return target.getDeserializationFilter();
         default: return null;
         }
     }
diff --git 
a/components/camel-infinispan/camel-infinispan/src/generated/resources/META-INF/services/org/apache/camel/bean/InfinispanRemoteKeyValueRepository.json
 
b/components/camel-infinispan/camel-infinispan/src/generated/resources/META-INF/services/org/apache/camel/bean/InfinispanRemoteKeyValueRepository.json
index 7a920e4f70b2..bce4c304e5c1 100644
--- 
a/components/camel-infinispan/camel-infinispan/src/generated/resources/META-INF/services/org/apache/camel/bean/InfinispanRemoteKeyValueRepository.json
+++ 
b/components/camel-infinispan/camel-infinispan/src/generated/resources/META-INF/services/org/apache/camel/bean/InfinispanRemoteKeyValueRepository.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-infinispan",
     "version": "4.23.0-SNAPSHOT",
-    "properties": { "cacheName": { "index": 0, "kind": "property", 
"displayName": "Cache Name", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "autowired": false, "secret": false, 
"description": "Name of cache" }, "configuration": { "index": 1, "kind": 
"property", "displayName": "Configuration", "required": false, "type": 
"object", "javaType": 
"org.apache.camel.component.infinispan.remote.InfinispanRemoteConfiguration", 
"deprecated": false, "auto [...]
+    "properties": { "cacheName": { "index": 0, "kind": "property", 
"displayName": "Cache Name", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "autowired": false, "secret": false, 
"description": "Name of cache" }, "configuration": { "index": 1, "kind": 
"property", "displayName": "Configuration", "required": false, "type": 
"object", "javaType": 
"org.apache.camel.component.infinispan.remote.InfinispanRemoteConfiguration", 
"deprecated": false, "auto [...]
   }
 }
 
diff --git 
a/components/camel-infinispan/camel-infinispan/src/main/java/org/apache/camel/component/infinispan/remote/InfinispanRemoteKeyValueRepository.java
 
b/components/camel-infinispan/camel-infinispan/src/main/java/org/apache/camel/component/infinispan/remote/InfinispanRemoteKeyValueRepository.java
index 19dafea30149..75861c551ccc 100644
--- 
a/components/camel-infinispan/camel-infinispan/src/main/java/org/apache/camel/component/infinispan/remote/InfinispanRemoteKeyValueRepository.java
+++ 
b/components/camel-infinispan/camel-infinispan/src/main/java/org/apache/camel/component/infinispan/remote/InfinispanRemoteKeyValueRepository.java
@@ -73,6 +73,13 @@ public class InfinispanRemoteKeyValueRepository extends 
ServiceSupport implement
     private String cacheName;
     @Metadata(description = "Configuration for remote Infinispan")
     private InfinispanRemoteConfiguration configuration;
+    @Metadata(label = "advanced,security",
+              description = "Sets an ObjectInputFilter pattern 
(jdk.serialFilter syntax) applied when deserializing"
+                            + " values read back from the repository. When not 
set, the JVM-wide jdk.serialFilter is"
+                            + " used if present; otherwise a conservative 
default filter denying java.net.* and"
+                            + " otherwise allowing java.*, javax.* and 
org.apache.camel.* packages is applied. Widen"
+                            + " this pattern when storing instances of your 
own classes in the repository.")
+    private String deserializationFilter;
 
     public InfinispanRemoteKeyValueRepository() {
     }
@@ -90,7 +97,7 @@ public class InfinispanRemoteKeyValueRepository extends 
ServiceSupport implement
     @ManagedOperation(description = "Get value by key")
     public @Nullable Object get(String key) {
         byte[] bytes = cache.get().get(key);
-        return bytes != null ? KeyValueRepositoryHelper.deserialize(bytes) : 
null;
+        return bytes != null ? KeyValueRepositoryHelper.deserialize(bytes, 
deserializationFilter) : null;
     }
 
     @Override
@@ -103,14 +110,14 @@ public class InfinispanRemoteKeyValueRepository extends 
ServiceSupport implement
         } else {
             previous = cache.get().put(key, serialized);
         }
-        return previous != null ? 
KeyValueRepositoryHelper.deserialize(previous) : null;
+        return previous != null ? 
KeyValueRepositoryHelper.deserialize(previous, deserializationFilter) : null;
     }
 
     @Override
     @ManagedOperation(description = "Delete a key")
     public @Nullable Object delete(String key) {
         byte[] bytes = cache.get().remove(key);
-        return bytes != null ? KeyValueRepositoryHelper.deserialize(bytes) : 
null;
+        return bytes != null ? KeyValueRepositoryHelper.deserialize(bytes, 
deserializationFilter) : null;
     }
 
     @Override
@@ -139,7 +146,7 @@ public class InfinispanRemoteKeyValueRepository extends 
ServiceSupport implement
         } else {
             existing = cache.get().putIfAbsent(key, serialized);
         }
-        return existing != null ? 
KeyValueRepositoryHelper.deserialize(existing) : null;
+        return existing != null ? 
KeyValueRepositoryHelper.deserialize(existing, deserializationFilter) : null;
     }
 
     /**
@@ -156,7 +163,7 @@ public class InfinispanRemoteKeyValueRepository extends 
ServiceSupport implement
         if (metadata == null) {
             return false;
         }
-        Object currentObj = 
KeyValueRepositoryHelper.deserialize(metadata.getValue());
+        Object currentObj = 
KeyValueRepositoryHelper.deserialize(metadata.getValue(), 
deserializationFilter);
         if (!Objects.equals(currentObj, expectedOldValue)) {
             return false;
         }
@@ -180,7 +187,7 @@ public class InfinispanRemoteKeyValueRepository extends 
ServiceSupport implement
         if (metadata == null) {
             return false;
         }
-        Object currentObj = 
KeyValueRepositoryHelper.deserialize(metadata.getValue());
+        Object currentObj = 
KeyValueRepositoryHelper.deserialize(metadata.getValue(), 
deserializationFilter);
         if (!Objects.equals(currentObj, expectedValue)) {
             return false;
         }
@@ -223,6 +230,20 @@ public class InfinispanRemoteKeyValueRepository extends 
ServiceSupport implement
         this.configuration.setCacheContainer(cacheContainer);
     }
 
+    public String getDeserializationFilter() {
+        return deserializationFilter;
+    }
+
+    /**
+     * Sets an {@link java.io.ObjectInputFilter} pattern (same syntax as 
{@code jdk.serialFilter}) applied when
+     * deserializing values read back from the repository. When not set, the 
JVM-wide {@code jdk.serialFilter} is used
+     * if present, otherwise a conservative default filter is applied. Widen 
this pattern when storing instances of your
+     * own classes in the repository.
+     */
+    public void setDeserializationFilter(String deserializationFilter) {
+        this.deserializationFilter = deserializationFilter;
+    }
+
     public InfinispanRemoteManager getManager() {
         return manager;
     }
diff --git 
a/components/camel-jpa/src/generated/java/org/apache/camel/processor/keyvalue/jpa/JpaKeyValueRepositoryConfigurer.java
 
b/components/camel-jpa/src/generated/java/org/apache/camel/processor/keyvalue/jpa/JpaKeyValueRepositoryConfigurer.java
index c7a43f4cd484..ce68724b80e6 100644
--- 
a/components/camel-jpa/src/generated/java/org/apache/camel/processor/keyvalue/jpa/JpaKeyValueRepositoryConfigurer.java
+++ 
b/components/camel-jpa/src/generated/java/org/apache/camel/processor/keyvalue/jpa/JpaKeyValueRepositoryConfigurer.java
@@ -23,6 +23,8 @@ public class JpaKeyValueRepositoryConfigurer extends 
org.apache.camel.support.co
     public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
         org.apache.camel.processor.keyvalue.jpa.JpaKeyValueRepository target = 
(org.apache.camel.processor.keyvalue.jpa.JpaKeyValueRepository) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "deserializationfilter":
+        case "deserializationFilter": 
target.setDeserializationFilter(property(camelContext, java.lang.String.class, 
value)); return true;
         case "entitymanagerfactory":
         case "entityManagerFactory": 
target.setEntityManagerFactory(property(camelContext, 
jakarta.persistence.EntityManagerFactory.class, value)); return true;
         case "jointransaction":
@@ -38,6 +40,8 @@ public class JpaKeyValueRepositoryConfigurer extends 
org.apache.camel.support.co
     @Override
     public Class<?> getOptionType(String name, boolean ignoreCase) {
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "deserializationfilter":
+        case "deserializationFilter": return java.lang.String.class;
         case "entitymanagerfactory":
         case "entityManagerFactory": return 
jakarta.persistence.EntityManagerFactory.class;
         case "jointransaction":
@@ -54,6 +58,8 @@ public class JpaKeyValueRepositoryConfigurer extends 
org.apache.camel.support.co
     public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
         org.apache.camel.processor.keyvalue.jpa.JpaKeyValueRepository target = 
(org.apache.camel.processor.keyvalue.jpa.JpaKeyValueRepository) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "deserializationfilter":
+        case "deserializationFilter": return target.getDeserializationFilter();
         case "entitymanagerfactory":
         case "entityManagerFactory": return target.getEntityManagerFactory();
         case "jointransaction":
diff --git 
a/components/camel-jpa/src/generated/resources/META-INF/services/org/apache/camel/bean/JpaKeyValueRepository.json
 
b/components/camel-jpa/src/generated/resources/META-INF/services/org/apache/camel/bean/JpaKeyValueRepository.json
index 2ec1140fe36b..6073d5e78960 100644
--- 
a/components/camel-jpa/src/generated/resources/META-INF/services/org/apache/camel/bean/JpaKeyValueRepository.json
+++ 
b/components/camel-jpa/src/generated/resources/META-INF/services/org/apache/camel/bean/JpaKeyValueRepository.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-jpa",
     "version": "4.23.0-SNAPSHOT",
-    "properties": { "entityManagerFactory": { "index": 0, "kind": "property", 
"displayName": "Entity Manager Factory", "required": true, "type": "object", 
"javaType": "jakarta.persistence.EntityManagerFactory", "deprecated": false, 
"autowired": false, "secret": false, "description": "The JPA 
EntityManagerFactory to use" }, "transactionStrategy": { "index": 1, "kind": 
"property", "displayName": "Transaction Strategy", "required": false, "type": 
"object", "javaType": "org.apache.camel.comp [...]
+    "properties": { "entityManagerFactory": { "index": 0, "kind": "property", 
"displayName": "Entity Manager Factory", "required": true, "type": "object", 
"javaType": "jakarta.persistence.EntityManagerFactory", "deprecated": false, 
"autowired": false, "secret": false, "description": "The JPA 
EntityManagerFactory to use" }, "transactionStrategy": { "index": 1, "kind": 
"property", "displayName": "Transaction Strategy", "required": false, "type": 
"object", "javaType": "org.apache.camel.comp [...]
   }
 }
 
diff --git 
a/components/camel-jpa/src/main/java/org/apache/camel/processor/keyvalue/jpa/JpaKeyValueRepository.java
 
b/components/camel-jpa/src/main/java/org/apache/camel/processor/keyvalue/jpa/JpaKeyValueRepository.java
index cea0eadf2443..104a7d96cad3 100644
--- 
a/components/camel-jpa/src/main/java/org/apache/camel/processor/keyvalue/jpa/JpaKeyValueRepository.java
+++ 
b/components/camel-jpa/src/main/java/org/apache/camel/processor/keyvalue/jpa/JpaKeyValueRepository.java
@@ -83,6 +83,13 @@ public class JpaKeyValueRepository extends ServiceSupport 
implements KeyValueRep
     private boolean joinTransaction = true;
     @Metadata(description = "Whether to use a shared EntityManager", 
defaultValue = "false")
     private boolean sharedEntityManager;
+    @Metadata(label = "advanced,security",
+              description = "Sets an ObjectInputFilter pattern 
(jdk.serialFilter syntax) applied when deserializing"
+                            + " values read back from the repository. When not 
set, the JVM-wide jdk.serialFilter is"
+                            + " used if present; otherwise a conservative 
default filter denying java.net.* and"
+                            + " otherwise allowing java.*, javax.* and 
org.apache.camel.* packages is applied. Widen"
+                            + " this pattern when storing instances of your 
own classes in the repository.")
+    private String deserializationFilter;
 
     /**
      * Creates a new JPA key-value repository. The {@link 
#setEntityManagerFactory(EntityManagerFactory)} must be called
@@ -122,7 +129,7 @@ public class JpaKeyValueRepository extends ServiceSupport 
implements KeyValueRep
                     entityManager.flush();
                     rc[0] = null;
                 } else {
-                    rc[0] = 
KeyValueRepositoryHelper.deserialize(entry.getItemValue());
+                    rc[0] = 
KeyValueRepositoryHelper.deserialize(entry.getItemValue(), 
deserializationFilter);
                 }
             } catch (Exception ex) {
                 String contextInfo = String.format(SOMETHING_WENT_WRONG, 
ex.getMessage());
@@ -154,7 +161,7 @@ public class JpaKeyValueRepository extends ServiceSupport 
implements KeyValueRep
                 KeyValueEntry entry = findByKey(entityManager, key);
                 if (entry != null) {
                     if (!entry.isExpired()) {
-                        rc[0] = 
KeyValueRepositoryHelper.deserialize(entry.getItemValue());
+                        rc[0] = 
KeyValueRepositoryHelper.deserialize(entry.getItemValue(), 
deserializationFilter);
                     }
                     entry.setItemValue(serializedValue);
                     entry.setExpiresAt(expiresAt);
@@ -196,7 +203,7 @@ public class JpaKeyValueRepository extends ServiceSupport 
implements KeyValueRep
                     entityManager.flush();
                     rc[0] = null;
                 } else {
-                    rc[0] = 
KeyValueRepositoryHelper.deserialize(entry.getItemValue());
+                    rc[0] = 
KeyValueRepositoryHelper.deserialize(entry.getItemValue(), 
deserializationFilter);
                     entityManager.remove(entry);
                     entityManager.flush();
                 }
@@ -324,7 +331,7 @@ public class JpaKeyValueRepository extends ServiceSupport 
implements KeyValueRep
                 KeyValueEntry entry = findByKey(entityManager, key);
                 if (entry != null && !entry.isExpired()) {
                     // key exists and is valid -- return existing value
-                    rc[0] = 
KeyValueRepositoryHelper.deserialize(entry.getItemValue());
+                    rc[0] = 
KeyValueRepositoryHelper.deserialize(entry.getItemValue(), 
deserializationFilter);
                 } else if (entry != null) {
                     // key exists but expired -- update in place
                     entry.setItemValue(serializedValue);
@@ -346,7 +353,8 @@ public class JpaKeyValueRepository extends ServiceSupport 
implements KeyValueRep
                     // re-read to return the existing value
                     try {
                         KeyValueEntry existing = findByKey(entityManager, key);
-                        rc[0] = existing != null ? 
KeyValueRepositoryHelper.deserialize(existing.getItemValue()) : null;
+                        rc[0] = existing != null
+                                ? 
KeyValueRepositoryHelper.deserialize(existing.getItemValue(), 
deserializationFilter) : null;
                     } catch (Exception inner) {
                         // fall through with null
                         rc[0] = null;
@@ -449,6 +457,20 @@ public class JpaKeyValueRepository extends ServiceSupport 
implements KeyValueRep
         this.sharedEntityManager = sharedEntityManager;
     }
 
+    public String getDeserializationFilter() {
+        return deserializationFilter;
+    }
+
+    /**
+     * Sets an {@link java.io.ObjectInputFilter} pattern (same syntax as 
{@code jdk.serialFilter}) applied when
+     * deserializing values read back from the repository. When not set, the 
JVM-wide {@code jdk.serialFilter} is used
+     * if present, otherwise a conservative default filter is applied. Widen 
this pattern when storing instances of your
+     * own classes in the repository.
+     */
+    public void setDeserializationFilter(String deserializationFilter) {
+        this.deserializationFilter = deserializationFilter;
+    }
+
     // ---- Lifecycle ----
 
     @Override
diff --git 
a/components/camel-kafka/src/generated/java/org/apache/camel/processor/keyvalue/kafka/KafkaKeyValueRepositoryConfigurer.java
 
b/components/camel-kafka/src/generated/java/org/apache/camel/processor/keyvalue/kafka/KafkaKeyValueRepositoryConfigurer.java
index 3707445d3ad3..6c20fd0eb022 100644
--- 
a/components/camel-kafka/src/generated/java/org/apache/camel/processor/keyvalue/kafka/KafkaKeyValueRepositoryConfigurer.java
+++ 
b/components/camel-kafka/src/generated/java/org/apache/camel/processor/keyvalue/kafka/KafkaKeyValueRepositoryConfigurer.java
@@ -27,6 +27,8 @@ public class KafkaKeyValueRepositoryConfigurer extends 
org.apache.camel.support.
         case "bootstrapServers": 
target.setBootstrapServers(property(camelContext, java.lang.String.class, 
value)); return true;
         case "consumerconfig":
         case "consumerConfig": target.setConsumerConfig(property(camelContext, 
java.util.Properties.class, value)); return true;
+        case "deserializationfilter":
+        case "deserializationFilter": 
target.setDeserializationFilter(property(camelContext, java.lang.String.class, 
value)); return true;
         case "groupid":
         case "groupId": target.setGroupId(property(camelContext, 
java.lang.String.class, value)); return true;
         case "maxcachesize":
@@ -49,6 +51,8 @@ public class KafkaKeyValueRepositoryConfigurer extends 
org.apache.camel.support.
         case "bootstrapServers": return java.lang.String.class;
         case "consumerconfig":
         case "consumerConfig": return java.util.Properties.class;
+        case "deserializationfilter":
+        case "deserializationFilter": return java.lang.String.class;
         case "groupid":
         case "groupId": return java.lang.String.class;
         case "maxcachesize":
@@ -72,6 +76,8 @@ public class KafkaKeyValueRepositoryConfigurer extends 
org.apache.camel.support.
         case "bootstrapServers": return target.getBootstrapServers();
         case "consumerconfig":
         case "consumerConfig": return target.getConsumerConfig();
+        case "deserializationfilter":
+        case "deserializationFilter": return target.getDeserializationFilter();
         case "groupid":
         case "groupId": return target.getGroupId();
         case "maxcachesize":
diff --git 
a/components/camel-kafka/src/generated/resources/META-INF/services/org/apache/camel/bean/KafkaKeyValueRepository.json
 
b/components/camel-kafka/src/generated/resources/META-INF/services/org/apache/camel/bean/KafkaKeyValueRepository.json
index dd228413c88e..d7c3d1900b55 100644
--- 
a/components/camel-kafka/src/generated/resources/META-INF/services/org/apache/camel/bean/KafkaKeyValueRepository.json
+++ 
b/components/camel-kafka/src/generated/resources/META-INF/services/org/apache/camel/bean/KafkaKeyValueRepository.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-kafka",
     "version": "4.23.0-SNAPSHOT",
-    "properties": { "consumerConfig": { "index": 0, "kind": "property", 
"displayName": "Consumer Config", "required": false, "type": "object", 
"javaType": "java.util.Properties", "deprecated": false, "autowired": false, 
"secret": false, "description": "Custom properties for the Kafka consumer" }, 
"producerConfig": { "index": 1, "kind": "property", "displayName": "Producer 
Config", "required": false, "type": "object", "javaType": 
"java.util.Properties", "deprecated": false, "autowired": f [...]
+    "properties": { "consumerConfig": { "index": 0, "kind": "property", 
"displayName": "Consumer Config", "required": false, "type": "object", 
"javaType": "java.util.Properties", "deprecated": false, "autowired": false, 
"secret": false, "description": "Custom properties for the Kafka consumer" }, 
"producerConfig": { "index": 1, "kind": "property", "displayName": "Producer 
Config", "required": false, "type": "object", "javaType": 
"java.util.Properties", "deprecated": false, "autowired": f [...]
   }
 }
 
diff --git 
a/components/camel-kafka/src/main/java/org/apache/camel/processor/keyvalue/kafka/KafkaKeyValueRepository.java
 
b/components/camel-kafka/src/main/java/org/apache/camel/processor/keyvalue/kafka/KafkaKeyValueRepository.java
index b793689919e8..ada853fa5503 100644
--- 
a/components/camel-kafka/src/main/java/org/apache/camel/processor/keyvalue/kafka/KafkaKeyValueRepository.java
+++ 
b/components/camel-kafka/src/main/java/org/apache/camel/processor/keyvalue/kafka/KafkaKeyValueRepository.java
@@ -141,6 +141,13 @@ public class KafkaKeyValueRepository extends 
ServiceSupport implements KeyValueR
     private int pollDurationMs = DEFAULT_POLL_DURATION_MS;
     @Metadata(description = "Whether to sync on startup only, or to continue 
syncing while Camel is running.")
     private boolean startupOnly;
+    @Metadata(label = "advanced,security",
+              description = "Sets an ObjectInputFilter pattern 
(jdk.serialFilter syntax) applied when deserializing"
+                            + " values read back from the repository. When not 
set, the JVM-wide jdk.serialFilter is"
+                            + " used if present; otherwise a conservative 
default filter denying java.net.* and"
+                            + " otherwise allowing java.*, javax.* and 
org.apache.camel.* packages is applied. Widen"
+                            + " this pattern when storing instances of your 
own classes in the repository.")
+    private String deserializationFilter;
 
     public KafkaKeyValueRepository() {
     }
@@ -356,7 +363,7 @@ public class KafkaKeyValueRepository extends ServiceSupport 
implements KeyValueR
 
     private Object deserializeValue(byte[] data) {
         // Value starts at offset 9 (1 byte action + 8 bytes expiresAt)
-        return KeyValueRepositoryHelper.deserialize(data, 9, data.length - 9);
+        return KeyValueRepositoryHelper.deserialize(data, 9, data.length - 9, 
deserializationFilter);
     }
 
     private long deserializeExpiresAt(byte[] data) {
@@ -678,6 +685,20 @@ public class KafkaKeyValueRepository extends 
ServiceSupport implements KeyValueR
         this.groupId = groupId;
     }
 
+    public String getDeserializationFilter() {
+        return deserializationFilter;
+    }
+
+    /**
+     * Sets an {@link java.io.ObjectInputFilter} pattern (same syntax as 
{@code jdk.serialFilter}) applied when
+     * deserializing values read back from the repository. When not set, the 
JVM-wide {@code jdk.serialFilter} is used
+     * if present, otherwise a conservative default filter is applied. Widen 
this pattern when storing instances of your
+     * own classes in the repository.
+     */
+    public void setDeserializationFilter(String deserializationFilter) {
+        this.deserializationFilter = deserializationFilter;
+    }
+
     @ManagedOperation(description = "Number of sync events received from the 
kafka topic")
     public long getCacheCounter() {
         return cacheCounter.get();
diff --git 
a/components/camel-redis/src/generated/java/org/apache/camel/component/redis/RedisKeyValueRepositoryConfigurer.java
 
b/components/camel-redis/src/generated/java/org/apache/camel/component/redis/RedisKeyValueRepositoryConfigurer.java
index 63e66174255e..f98b33c44a77 100644
--- 
a/components/camel-redis/src/generated/java/org/apache/camel/component/redis/RedisKeyValueRepositoryConfigurer.java
+++ 
b/components/camel-redis/src/generated/java/org/apache/camel/component/redis/RedisKeyValueRepositoryConfigurer.java
@@ -23,6 +23,8 @@ public class RedisKeyValueRepositoryConfigurer extends 
org.apache.camel.support.
     public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
         org.apache.camel.component.redis.RedisKeyValueRepository target = 
(org.apache.camel.component.redis.RedisKeyValueRepository) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "deserializationfilter":
+        case "deserializationFilter": 
target.setDeserializationFilter(property(camelContext, java.lang.String.class, 
value)); return true;
         case "endpoint": target.setEndpoint(property(camelContext, 
java.lang.String.class, value)); return true;
         case "keyprefix":
         case "keyPrefix": target.setKeyPrefix(property(camelContext, 
java.lang.String.class, value)); return true;
@@ -34,6 +36,8 @@ public class RedisKeyValueRepositoryConfigurer extends 
org.apache.camel.support.
     @Override
     public Class<?> getOptionType(String name, boolean ignoreCase) {
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "deserializationfilter":
+        case "deserializationFilter": return java.lang.String.class;
         case "endpoint": return java.lang.String.class;
         case "keyprefix":
         case "keyPrefix": return java.lang.String.class;
@@ -46,6 +50,8 @@ public class RedisKeyValueRepositoryConfigurer extends 
org.apache.camel.support.
     public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
         org.apache.camel.component.redis.RedisKeyValueRepository target = 
(org.apache.camel.component.redis.RedisKeyValueRepository) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "deserializationfilter":
+        case "deserializationFilter": return target.getDeserializationFilter();
         case "endpoint": return target.getEndpoint();
         case "keyprefix":
         case "keyPrefix": return target.getKeyPrefix();
diff --git 
a/components/camel-redis/src/generated/resources/META-INF/services/org/apache/camel/bean/RedisKeyValueRepository.json
 
b/components/camel-redis/src/generated/resources/META-INF/services/org/apache/camel/bean/RedisKeyValueRepository.json
index 35fad0e6c77f..c8fc56830883 100644
--- 
a/components/camel-redis/src/generated/resources/META-INF/services/org/apache/camel/bean/RedisKeyValueRepository.json
+++ 
b/components/camel-redis/src/generated/resources/META-INF/services/org/apache/camel/bean/RedisKeyValueRepository.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-redis",
     "version": "4.23.0-SNAPSHOT",
-    "properties": { "redisson": { "index": 0, "kind": "property", 
"displayName": "Redisson", "label": "advanced", "required": false, "type": 
"object", "javaType": "org.redisson.api.RedissonClient", "deprecated": false, 
"autowired": false, "secret": false, "description": "To use an existing 
Redisson client to connect to Redis server" }, "endpoint": { "index": 1, 
"kind": "property", "displayName": "Endpoint", "required": true, "type": 
"string", "javaType": "java.lang.String", "deprecated": [...]
+    "properties": { "redisson": { "index": 0, "kind": "property", 
"displayName": "Redisson", "label": "advanced", "required": false, "type": 
"object", "javaType": "org.redisson.api.RedissonClient", "deprecated": false, 
"autowired": false, "secret": false, "description": "To use an existing 
Redisson client to connect to Redis server" }, "endpoint": { "index": 1, 
"kind": "property", "displayName": "Endpoint", "required": true, "type": 
"string", "javaType": "java.lang.String", "deprecated": [...]
   }
 }
 
diff --git 
a/components/camel-redis/src/main/java/org/apache/camel/component/redis/RedisKeyValueRepository.java
 
b/components/camel-redis/src/main/java/org/apache/camel/component/redis/RedisKeyValueRepository.java
index 687194885cdb..eca75084e86c 100644
--- 
a/components/camel-redis/src/main/java/org/apache/camel/component/redis/RedisKeyValueRepository.java
+++ 
b/components/camel-redis/src/main/java/org/apache/camel/component/redis/RedisKeyValueRepository.java
@@ -67,6 +67,13 @@ public class RedisKeyValueRepository extends ServiceSupport 
implements KeyValueR
     private String endpoint;
     @Metadata(description = "Key prefix used to namespace entries in Redis", 
defaultValue = "camel-kvr:")
     private String keyPrefix = "camel-kvr:";
+    @Metadata(label = "advanced,security",
+              description = "Sets an ObjectInputFilter pattern 
(jdk.serialFilter syntax) applied when deserializing"
+                            + " values read back from the repository. When not 
set, the JVM-wide jdk.serialFilter is"
+                            + " used if present; otherwise a conservative 
default filter denying java.net.* and"
+                            + " otherwise allowing java.*, javax.* and 
org.apache.camel.* packages is applied. Widen"
+                            + " this pattern when storing instances of your 
own classes in the repository.")
+    private String deserializationFilter;
 
     public RedisKeyValueRepository() {
     }
@@ -96,7 +103,7 @@ public class RedisKeyValueRepository extends ServiceSupport 
implements KeyValueR
     public @Nullable Object get(String key) {
         RBucket<byte[]> bucket = redisson.getBucket(toRedisKey(key), 
ByteArrayCodec.INSTANCE);
         byte[] bytes = bucket.get();
-        return bytes != null ? KeyValueRepositoryHelper.deserialize(bytes) : 
null;
+        return bytes != null ? KeyValueRepositoryHelper.deserialize(bytes, 
deserializationFilter) : null;
     }
 
     @Override
@@ -110,7 +117,7 @@ public class RedisKeyValueRepository extends ServiceSupport 
implements KeyValueR
         } else {
             previous = bucket.getAndSet(serialized);
         }
-        return previous != null ? 
KeyValueRepositoryHelper.deserialize(previous) : null;
+        return previous != null ? 
KeyValueRepositoryHelper.deserialize(previous, deserializationFilter) : null;
     }
 
     @Override
@@ -118,7 +125,7 @@ public class RedisKeyValueRepository extends ServiceSupport 
implements KeyValueR
     public @Nullable Object delete(String key) {
         RBucket<byte[]> bucket = redisson.getBucket(toRedisKey(key), 
ByteArrayCodec.INSTANCE);
         byte[] bytes = bucket.getAndDelete();
-        return bytes != null ? KeyValueRepositoryHelper.deserialize(bytes) : 
null;
+        return bytes != null ? KeyValueRepositoryHelper.deserialize(bytes, 
deserializationFilter) : null;
     }
 
     @Override
@@ -160,7 +167,7 @@ public class RedisKeyValueRepository extends ServiceSupport 
implements KeyValueR
         }
         // Key already existed; return the current value
         byte[] existing = bucket.get();
-        return existing != null ? 
KeyValueRepositoryHelper.deserialize(existing) : null;
+        return existing != null ? 
KeyValueRepositoryHelper.deserialize(existing, deserializationFilter) : null;
     }
 
     /**
@@ -223,6 +230,20 @@ public class RedisKeyValueRepository extends 
ServiceSupport implements KeyValueR
         this.redisson = redisson;
     }
 
+    public String getDeserializationFilter() {
+        return deserializationFilter;
+    }
+
+    /**
+     * Sets an {@link java.io.ObjectInputFilter} pattern (same syntax as 
{@code jdk.serialFilter}) applied when
+     * deserializing values read back from the repository. When not set, the 
JVM-wide {@code jdk.serialFilter} is used
+     * if present, otherwise a conservative default filter is applied. Widen 
this pattern when storing instances of your
+     * own classes in the repository.
+     */
+    public void setDeserializationFilter(String deserializationFilter) {
+        this.deserializationFilter = deserializationFilter;
+    }
+
     // ---- Lifecycle ----
 
     @Override
diff --git 
a/components/camel-sql/src/generated/java/org/apache/camel/processor/keyvalue/jdbc/JdbcKeyValueRepositoryConfigurer.java
 
b/components/camel-sql/src/generated/java/org/apache/camel/processor/keyvalue/jdbc/JdbcKeyValueRepositoryConfigurer.java
index 377981ec7fcc..ee2a16c8c1ad 100644
--- 
a/components/camel-sql/src/generated/java/org/apache/camel/processor/keyvalue/jdbc/JdbcKeyValueRepositoryConfigurer.java
+++ 
b/components/camel-sql/src/generated/java/org/apache/camel/processor/keyvalue/jdbc/JdbcKeyValueRepositoryConfigurer.java
@@ -35,6 +35,8 @@ public class JdbcKeyValueRepositoryConfigurer extends 
org.apache.camel.support.c
         case "deleteIfValueString": 
target.setDeleteIfValueString(property(camelContext, java.lang.String.class, 
value)); return true;
         case "deletestring":
         case "deleteString": target.setDeleteString(property(camelContext, 
java.lang.String.class, value)); return true;
+        case "deserializationfilter":
+        case "deserializationFilter": 
target.setDeserializationFilter(property(camelContext, java.lang.String.class, 
value)); return true;
         case "insertstring":
         case "insertString": target.setInsertString(property(camelContext, 
java.lang.String.class, value)); return true;
         case "jdbctemplate":
@@ -70,6 +72,8 @@ public class JdbcKeyValueRepositoryConfigurer extends 
org.apache.camel.support.c
         case "deleteIfValueString": return java.lang.String.class;
         case "deletestring":
         case "deleteString": return java.lang.String.class;
+        case "deserializationfilter":
+        case "deserializationFilter": return java.lang.String.class;
         case "insertstring":
         case "insertString": return java.lang.String.class;
         case "jdbctemplate":
@@ -106,6 +110,8 @@ public class JdbcKeyValueRepositoryConfigurer extends 
org.apache.camel.support.c
         case "deleteIfValueString": return target.getDeleteIfValueString();
         case "deletestring":
         case "deleteString": return target.getDeleteString();
+        case "deserializationfilter":
+        case "deserializationFilter": return target.getDeserializationFilter();
         case "insertstring":
         case "insertString": return target.getInsertString();
         case "jdbctemplate":
diff --git 
a/components/camel-sql/src/generated/resources/META-INF/services/org/apache/camel/bean/JdbcKeyValueRepository.json
 
b/components/camel-sql/src/generated/resources/META-INF/services/org/apache/camel/bean/JdbcKeyValueRepository.json
index 07bc8667d665..2042d4a6633e 100644
--- 
a/components/camel-sql/src/generated/resources/META-INF/services/org/apache/camel/bean/JdbcKeyValueRepository.json
+++ 
b/components/camel-sql/src/generated/resources/META-INF/services/org/apache/camel/bean/JdbcKeyValueRepository.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-sql",
     "version": "4.23.0-SNAPSHOT",
-    "properties": { "jdbcTemplate": { "index": 0, "kind": "property", 
"displayName": "Jdbc Template", "required": true, "type": "object", "javaType": 
"org.springframework.jdbc.core.JdbcTemplate", "deprecated": false, "autowired": 
false, "secret": false, "description": "The Spring JdbcTemplate to use for 
connecting to the database" }, "transactionTemplate": { "index": 1, "kind": 
"property", "displayName": "Transaction Template", "required": true, "type": 
"object", "javaType": "org.springf [...]
+    "properties": { "jdbcTemplate": { "index": 0, "kind": "property", 
"displayName": "Jdbc Template", "required": true, "type": "object", "javaType": 
"org.springframework.jdbc.core.JdbcTemplate", "deprecated": false, "autowired": 
false, "secret": false, "description": "The Spring JdbcTemplate to use for 
connecting to the database" }, "transactionTemplate": { "index": 1, "kind": 
"property", "displayName": "Transaction Template", "required": true, "type": 
"object", "javaType": "org.springf [...]
   }
 }
 
diff --git 
a/components/camel-sql/src/main/java/org/apache/camel/processor/keyvalue/jdbc/JdbcKeyValueRepository.java
 
b/components/camel-sql/src/main/java/org/apache/camel/processor/keyvalue/jdbc/JdbcKeyValueRepository.java
index 47eadd3efd77..f05b43b16a2d 100644
--- 
a/components/camel-sql/src/main/java/org/apache/camel/processor/keyvalue/jdbc/JdbcKeyValueRepository.java
+++ 
b/components/camel-sql/src/main/java/org/apache/camel/processor/keyvalue/jdbc/JdbcKeyValueRepository.java
@@ -113,6 +113,13 @@ public class JdbcKeyValueRepository extends ServiceSupport 
implements KeyValueRe
     private String updateIfValueString = DEFAULT_UPDATE_IF_VALUE_STRING;
     @Metadata(label = "advanced", description = "SQL query to use for 
conditional delete (CAS delete)")
     private String deleteIfValueString = DEFAULT_DELETE_IF_VALUE_STRING;
+    @Metadata(label = "advanced,security",
+              description = "Sets an ObjectInputFilter pattern 
(jdk.serialFilter syntax) applied when deserializing"
+                            + " values read back from the repository. When not 
set, the JVM-wide jdk.serialFilter is"
+                            + " used if present; otherwise a conservative 
default filter denying java.net.* and"
+                            + " otherwise allowing java.*, javax.* and 
org.apache.camel.* packages is applied. Widen"
+                            + " this pattern when storing instances of your 
own classes in the repository.")
+    private String deserializationFilter;
 
     /**
      * Creates a new JDBC key-value repository. A {@link DataSource} or {@link 
JdbcTemplate} must be set before
@@ -373,7 +380,7 @@ public class JdbcKeyValueRepository extends ServiceSupport 
implements KeyValueRe
                     expired[0] = true;
                     return null;
                 }
-                return KeyValueRepositoryHelper.deserialize(bytes);
+                return KeyValueRepositoryHelper.deserialize(bytes, 
deserializationFilter);
             }, key);
             if (expired[0]) {
                 jdbcTemplate.update(getDeleteString(), key);
@@ -518,4 +525,18 @@ public class JdbcKeyValueRepository extends ServiceSupport 
implements KeyValueRe
     public void setDeleteIfValueString(String deleteIfValueString) {
         this.deleteIfValueString = deleteIfValueString;
     }
+
+    public String getDeserializationFilter() {
+        return deserializationFilter;
+    }
+
+    /**
+     * Sets an {@link java.io.ObjectInputFilter} pattern (same syntax as 
{@code jdk.serialFilter}) applied when
+     * deserializing values read back from the repository. When not set, the 
JVM-wide {@code jdk.serialFilter} is used
+     * if present, otherwise a conservative default filter is applied. Widen 
this pattern when storing instances of your
+     * own classes in the repository.
+     */
+    public void setDeserializationFilter(String deserializationFilter) {
+        this.deserializationFilter = deserializationFilter;
+    }
 }
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/KeyValueRepositoryHelper.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/KeyValueRepositoryHelper.java
index 13d3ff696456..87c143a0afb7 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/KeyValueRepositoryHelper.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/KeyValueRepositoryHelper.java
@@ -19,6 +19,7 @@ package org.apache.camel.support;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.ObjectInputFilter;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.nio.ByteBuffer;
@@ -33,8 +34,12 @@ import org.apache.camel.RuntimeCamelException;
  * try/catch boilerplate in every implementation.
  * <p/>
  * <b>Security note:</b> These methods use plain Java serialization
- * ({@link ObjectOutputStream}/{@link ObjectInputStream}). The stored data is 
trusted — it was written by the same
- * application instance or cluster. Do not expose a repository's raw byte 
store to untrusted input.
+ * ({@link ObjectOutputStream}/{@link ObjectInputStream}). The byte store 
backing a repository is shared infrastructure
+ * (a Redis instance, a database table, a Kafka topic, a data grid) and is not 
necessarily writable only by the
+ * application that owns it. Every {@code deserialize} method therefore 
installs a JEP-290 {@link ObjectInputFilter}
+ * resolved by {@link DeserializationFilterHelper}, in the same way the 
aggregation repositories do. The default filter
+ * only allows standard Java and Apache Camel types, so applications that 
store their own classes must widen it through
+ * the {@code deserializationFilter} option of the repository they use.
  *
  * @since 4.23
  */
@@ -75,21 +80,48 @@ public final class KeyValueRepositoryHelper {
     }
 
     /**
-     * Deserializes a byte array back into an object using Java object 
serialization.
+     * Deserializes a byte array back into an object using Java object 
serialization, applying the default
+     * deserialization filter.
      *
      * @param  bytes                 the bytes to deserialize
      * @return                       the deserialized object
-     * @throws RuntimeCamelException if deserialization fails
+     * @throws RuntimeCamelException if deserialization fails or the filter 
rejects the stream
      */
     public static Object deserialize(byte[] bytes) {
-        try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
-             ObjectInputStream ois = new ObjectInputStream(bis)) {
-            return ois.readObject();
+        return deserialize(bytes, null);
+    }
+
+    /**
+     * Deserializes a byte array back into an object using Java object 
serialization.
+     *
+     * @param  bytes                 the bytes to deserialize
+     * @param  deserializationFilter the filter pattern to apply, or null to 
use the JVM-wide filter or the Camel
+     *                               default
+     * @return                       the deserialized object
+     * @throws RuntimeCamelException if deserialization fails or the filter 
rejects the stream
+     */
+    public static Object deserialize(byte[] bytes, String 
deserializationFilter) {
+        try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes)) {
+            return doDeserialize(bis, deserializationFilter);
         } catch (IOException | ClassNotFoundException e) {
             throw new RuntimeCamelException("Failed to deserialize value", e);
         }
     }
 
+    /**
+     * Deserializes an object from a portion of a byte array using Java object 
serialization, applying the default
+     * deserialization filter. Useful when the serialized data starts at an 
offset (e.g. after a protocol header).
+     *
+     * @param  bytes                 the byte array containing the serialized 
data
+     * @param  offset                the start offset within the array
+     * @param  length                the number of bytes to read
+     * @return                       the deserialized object
+     * @throws RuntimeCamelException if deserialization fails or the filter 
rejects the stream
+     */
+    public static Object deserialize(byte[] bytes, int offset, int length) {
+        return deserialize(bytes, offset, length, null);
+    }
+
     /**
      * Deserializes an object from a portion of a byte array using Java object 
serialization. Useful when the serialized
      * data starts at an offset (e.g. after a protocol header).
@@ -97,29 +129,52 @@ public final class KeyValueRepositoryHelper {
      * @param  bytes                 the byte array containing the serialized 
data
      * @param  offset                the start offset within the array
      * @param  length                the number of bytes to read
+     * @param  deserializationFilter the filter pattern to apply, or null to 
use the JVM-wide filter or the Camel
+     *                               default
      * @return                       the deserialized object
-     * @throws RuntimeCamelException if deserialization fails
+     * @throws RuntimeCamelException if deserialization fails or the filter 
rejects the stream
      */
-    public static Object deserialize(byte[] bytes, int offset, int length) {
-        try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes, 
offset, length);
-             ObjectInputStream ois = new ObjectInputStream(bis)) {
-            return ois.readObject();
+    public static Object deserialize(byte[] bytes, int offset, int length, 
String deserializationFilter) {
+        try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes, 
offset, length)) {
+            return doDeserialize(bis, deserializationFilter);
         } catch (IOException | ClassNotFoundException e) {
             throw new RuntimeCamelException("Failed to deserialize value", e);
         }
     }
 
+    /**
+     * Deserializes an object from a {@link ByteBuffer} using Java object 
serialization, applying the default
+     * deserialization filter. The buffer's remaining bytes are consumed.
+     *
+     * @param  buffer                the ByteBuffer containing the serialized 
bytes
+     * @return                       the deserialized object
+     * @throws RuntimeCamelException if deserialization fails or the filter 
rejects the stream
+     */
+    public static Object deserialize(ByteBuffer buffer) {
+        return deserialize(buffer, null);
+    }
+
     /**
      * Deserializes an object from a {@link ByteBuffer} using Java object 
serialization. The buffer's remaining bytes
      * are consumed.
      *
      * @param  buffer                the ByteBuffer containing the serialized 
bytes
+     * @param  deserializationFilter the filter pattern to apply, or null to 
use the JVM-wide filter or the Camel
+     *                               default
      * @return                       the deserialized object
-     * @throws RuntimeCamelException if deserialization fails
+     * @throws RuntimeCamelException if deserialization fails or the filter 
rejects the stream
      */
-    public static Object deserialize(ByteBuffer buffer) {
+    public static Object deserialize(ByteBuffer buffer, String 
deserializationFilter) {
         byte[] bytes = new byte[buffer.remaining()];
         buffer.get(bytes);
-        return deserialize(bytes);
+        return deserialize(bytes, deserializationFilter);
+    }
+
+    private static Object doDeserialize(ByteArrayInputStream bis, String 
deserializationFilter)
+            throws IOException, ClassNotFoundException {
+        try (ObjectInputStream ois = new ObjectInputStream(bis)) {
+            
ois.setObjectInputFilter(DeserializationFilterHelper.resolveDeserializationFilter(deserializationFilter));
+            return ois.readObject();
+        }
     }
 }
diff --git 
a/core/camel-support/src/test/java/org/apache/camel/support/KeyValueRepositoryHelperTest.java
 
b/core/camel-support/src/test/java/org/apache/camel/support/KeyValueRepositoryHelperTest.java
index 0977b39c41b0..8ae3f86c6c3c 100644
--- 
a/core/camel-support/src/test/java/org/apache/camel/support/KeyValueRepositoryHelperTest.java
+++ 
b/core/camel-support/src/test/java/org/apache/camel/support/KeyValueRepositoryHelperTest.java
@@ -16,8 +16,10 @@
  */
 package org.apache.camel.support;
 
+import java.io.InvalidClassException;
 import java.io.Serial;
 import java.io.Serializable;
+import java.net.URI;
 import java.nio.ByteBuffer;
 import java.util.List;
 import java.util.Map;
@@ -271,6 +273,78 @@ class KeyValueRepositoryHelperTest {
         assertThat(result).isNull();
     }
 
+    // 
-------------------------------------------------------------------------
+    // Deserialization filter
+    // 
-------------------------------------------------------------------------
+
+    @Test
+    void testDefaultFilterRejectsDeniedClass() {
+        // java.net.** is denied by the default filter as those classes may 
perform network I/O in hashCode/equals
+        byte[] bytes = 
KeyValueRepositoryHelper.serialize(URI.create("http://localhost:8080/camel";));
+
+        assertThatThrownBy(() -> KeyValueRepositoryHelper.deserialize(bytes))
+                .isInstanceOf(RuntimeCamelException.class)
+                .hasMessageContaining("Failed to deserialize value")
+                .hasRootCauseInstanceOf(InvalidClassException.class);
+    }
+
+    @Test
+    void testDefaultFilterAllowsCamelAndJavaClasses() {
+        ComplexPayload original = new ComplexPayload("order-1", 1, 
List.of("item-a"));
+
+        byte[] bytes = KeyValueRepositoryHelper.serialize(original);
+
+        
assertThat(KeyValueRepositoryHelper.deserialize(bytes)).isEqualTo(original);
+    }
+
+    @Test
+    void testCustomFilterCanWidenTheAllowList() {
+        URI original = URI.create("http://localhost:8080/camel";);
+        byte[] bytes = KeyValueRepositoryHelper.serialize(original);
+
+        Object result = KeyValueRepositoryHelper.deserialize(bytes, 
"java.net.**;java.**;!*");
+
+        assertThat(result).isEqualTo(original);
+    }
+
+    @Test
+    void testCustomFilterCanNarrowTheAllowList() {
+        // note: java.lang.String is written as TC_STRING and never passes 
through the filter, so use a boxed number
+        byte[] bytes = KeyValueRepositoryHelper.serialize(42);
+
+        assertThatThrownBy(() -> KeyValueRepositoryHelper.deserialize(bytes, 
"!*"))
+                .isInstanceOf(RuntimeCamelException.class)
+                .hasMessageContaining("Failed to deserialize value")
+                .hasRootCauseInstanceOf(InvalidClassException.class);
+    }
+
+    @Test
+    void testCustomFilterAppliedOnOffsetVariant() {
+        URI original = URI.create("http://localhost:8080/camel";);
+        byte[] bytes = KeyValueRepositoryHelper.serialize(original);
+
+        assertThatThrownBy(() -> KeyValueRepositoryHelper.deserialize(bytes, 
0, bytes.length))
+                .isInstanceOf(RuntimeCamelException.class)
+                .hasRootCauseInstanceOf(InvalidClassException.class);
+
+        assertThat(KeyValueRepositoryHelper.deserialize(bytes, 0, 
bytes.length, "java.net.**;java.**;!*"))
+                .isEqualTo(original);
+    }
+
+    @Test
+    void testCustomFilterAppliedOnByteBufferVariant() {
+        URI original = URI.create("http://localhost:8080/camel";);
+
+        assertThatThrownBy(() -> KeyValueRepositoryHelper.deserialize(
+                KeyValueRepositoryHelper.serializeToByteBuffer(original)))
+                .isInstanceOf(RuntimeCamelException.class)
+                .hasRootCauseInstanceOf(InvalidClassException.class);
+
+        assertThat(KeyValueRepositoryHelper.deserialize(
+                KeyValueRepositoryHelper.serializeToByteBuffer(original), 
"java.net.**;java.**;!*"))
+                .isEqualTo(original);
+    }
+
     // 
-------------------------------------------------------------------------
     // Helper types
     // 
-------------------------------------------------------------------------
diff --git a/docs/user-manual/modules/ROOT/pages/key-value-repository.adoc 
b/docs/user-manual/modules/ROOT/pages/key-value-repository.adoc
index 8fdefdbc4478..1b7e44909e35 100644
--- a/docs/user-manual/modules/ROOT/pages/key-value-repository.adoc
+++ b/docs/user-manual/modules/ROOT/pages/key-value-repository.adoc
@@ -260,6 +260,41 @@ repo.setCacheName("camel-kvr");  // optional
 
 Fully atomic CAS operations including `replace` with TTL in a single native 
call.
 
+== Serialization
+
+The persistent backends (JDBC, JPA, Cassandra, Kafka, Hazelcast, Redis and 
Infinispan) store values
+as bytes produced by plain Java serialization, via the shared 
`KeyValueRepositoryHelper`. Values must
+therefore implement `java.io.Serializable`.
+
+Because the byte store behind those backends is shared infrastructure -- a 
database table, a Kafka
+topic, a Redis instance, a data grid -- reading an entry back is a 
deserialization of data that Camel
+did not necessarily write. Every read therefore installs a JEP-290 
`java.io.ObjectInputFilter`,
+exactly as the aggregation repositories do.
+
+By default the filter denies `java.net.*` and otherwise allows `java.*`, 
`javax.*` and
+`org.apache.camel.*`, with the JEP-290 graph-shape limits `maxdepth`, 
`maxrefs` and `maxbytes` applied
+as defense-in-depth. If the JVM-wide `jdk.serialFilter` system property is 
set, it takes precedence
+over the Camel default.
+
+This means that storing instances of your *own* classes requires widening the 
filter through the
+`deserializationFilter` option, which every persistent backend exposes:
+
+[source,java]
+----
+RedisKeyValueRepository repo = new RedisKeyValueRepository("localhost:6379");
+repo.setDeserializationFilter("com.mycompany.model.**;java.**;javax.**;org.apache.camel.**;!*");
+----
+
+The pattern uses the same syntax as `jdk.serialFilter`. Keep it as narrow as 
possible: a permissive
+pattern such as `*` re-opens the repository to arbitrary gadget classes.
+
+The same applies indirectly when a persistent backend is used through 
`KeyValueAggregationRepository`:
+the aggregated exchange is stored as a `DefaultExchangeHolder`, so the message 
body and any serialized
+header types must be covered by the filter as well.
+
+The in-memory backends (Memory, Caffeine, Ehcache, JCache) keep object 
references and do not
+serialize, so they have no `deserializationFilter` option.
+
 == Usage with Camel Patterns
 
 === Single backend, multiple patterns

Reply via email to