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

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

commit 5f343367f7b25646b7d12be26c3e87381c7a7ecb
Author: Andrea Cosentino <[email protected]>
AuthorDate: Fri Feb 6 10:21:36 2026 +0100

    CAMEL-22966 - Camel-LevelDB: Add ObjectInputFilter String pattern parameter 
in LevelDBAggregationRepository to be used in unmarshall operations
    
    Signed-off-by: Andrea Cosentino <[email protected]>
---
 .../beans/LevelDBAggregationRepository.json        |  2 +-
 .../LevelDBAggregationRepositoryConfigurer.java    |  6 ++++
 .../camel/bean/LevelDBAggregationRepository.json   |  2 +-
 .../camel-leveldb/src/main/docs/leveldb.adoc       |  8 +++++
 .../leveldb/LevelDBAggregationRepository.java      | 34 ++++++++++++++++++----
 .../camel/component/leveldb/LevelDBCamelCodec.java | 15 ++++++++++
 .../camel/component/leveldb/LevelDBSerializer.java | 18 ++++++++++++
 .../serializer/DefaultLevelDBSerializer.java       | 18 ++++++++++++
 8 files changed, 95 insertions(+), 8 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/LevelDBAggregationRepository.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/LevelDBAggregationRepository.json
index f88ea99bf408..5f374f0d5d8a 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/LevelDBAggregationRepository.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/beans/LevelDBAggregationRepository.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-leveldb",
     "version": "4.18.0-SNAPSHOT",
-    "properties": { "persistentFileName": { "index": 0, "kind": "property", 
"displayName": "Persistent File Name", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "description": "Name of file to use for storing data" }, 
"repositoryName": { "index": 1, "kind": "property", "displayName": "Repository 
Name", "required": true, "type": "string", "javaType": "java.lang.String", 
"deprecated": false, "autowired": false, [...]
+    "properties": { "persistentFileName": { "index": 0, "kind": "property", 
"displayName": "Persistent File Name", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "description": "Name of file to use for storing data" }, 
"repositoryName": { "index": 1, "kind": "property", "displayName": "Repository 
Name", "required": true, "type": "string", "javaType": "java.lang.String", 
"deprecated": false, "autowired": false, [...]
   }
 }
 
diff --git 
a/components/camel-leveldb/src/generated/java/org/apache/camel/component/leveldb/LevelDBAggregationRepositoryConfigurer.java
 
b/components/camel-leveldb/src/generated/java/org/apache/camel/component/leveldb/LevelDBAggregationRepositoryConfigurer.java
index 6a8069a14c33..5cc2934338f9 100644
--- 
a/components/camel-leveldb/src/generated/java/org/apache/camel/component/leveldb/LevelDBAggregationRepositoryConfigurer.java
+++ 
b/components/camel-leveldb/src/generated/java/org/apache/camel/component/leveldb/LevelDBAggregationRepositoryConfigurer.java
@@ -27,6 +27,8 @@ public class LevelDBAggregationRepositoryConfigurer extends 
org.apache.camel.sup
         case "allowSerializedHeaders": 
target.setAllowSerializedHeaders(property(camelContext, boolean.class, value)); 
return true;
         case "deadletteruri":
         case "deadLetterUri": target.setDeadLetterUri(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 "maximumredeliveries":
         case "maximumRedeliveries": 
target.setMaximumRedeliveries(property(camelContext, int.class, value)); return 
true;
         case "persistentfilename":
@@ -52,6 +54,8 @@ public class LevelDBAggregationRepositoryConfigurer extends 
org.apache.camel.sup
         case "allowSerializedHeaders": return boolean.class;
         case "deadletteruri":
         case "deadLetterUri": return java.lang.String.class;
+        case "deserializationfilter":
+        case "deserializationFilter": return java.lang.String.class;
         case "maximumredeliveries":
         case "maximumRedeliveries": return int.class;
         case "persistentfilename":
@@ -78,6 +82,8 @@ public class LevelDBAggregationRepositoryConfigurer extends 
org.apache.camel.sup
         case "allowSerializedHeaders": return 
target.isAllowSerializedHeaders();
         case "deadletteruri":
         case "deadLetterUri": return target.getDeadLetterUri();
+        case "deserializationfilter":
+        case "deserializationFilter": return target.getDeserializationFilter();
         case "maximumredeliveries":
         case "maximumRedeliveries": return target.getMaximumRedeliveries();
         case "persistentfilename":
diff --git 
a/components/camel-leveldb/src/generated/resources/META-INF/services/org/apache/camel/bean/LevelDBAggregationRepository.json
 
b/components/camel-leveldb/src/generated/resources/META-INF/services/org/apache/camel/bean/LevelDBAggregationRepository.json
index f88ea99bf408..5f374f0d5d8a 100644
--- 
a/components/camel-leveldb/src/generated/resources/META-INF/services/org/apache/camel/bean/LevelDBAggregationRepository.json
+++ 
b/components/camel-leveldb/src/generated/resources/META-INF/services/org/apache/camel/bean/LevelDBAggregationRepository.json
@@ -10,7 +10,7 @@
     "groupId": "org.apache.camel",
     "artifactId": "camel-leveldb",
     "version": "4.18.0-SNAPSHOT",
-    "properties": { "persistentFileName": { "index": 0, "kind": "property", 
"displayName": "Persistent File Name", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "description": "Name of file to use for storing data" }, 
"repositoryName": { "index": 1, "kind": "property", "displayName": "Repository 
Name", "required": true, "type": "string", "javaType": "java.lang.String", 
"deprecated": false, "autowired": false, [...]
+    "properties": { "persistentFileName": { "index": 0, "kind": "property", 
"displayName": "Persistent File Name", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "description": "Name of file to use for storing data" }, 
"repositoryName": { "index": 1, "kind": "property", "displayName": "Repository 
Name", "required": true, "type": "string", "javaType": "java.lang.String", 
"deprecated": false, "autowired": false, [...]
   }
 }
 
diff --git a/components/camel-leveldb/src/main/docs/leveldb.adoc 
b/components/camel-leveldb/src/main/docs/leveldb.adoc
index 0508f7f05a4d..c7556f69432f 100644
--- a/components/camel-leveldb/src/main/docs/leveldb.adoc
+++ b/components/camel-leveldb/src/main/docs/leveldb.adoc
@@ -71,6 +71,14 @@ option must also be provided.
 |`deadLetterUri` |String |An endpoint uri for a Dead Letter Channel
 where exhausted recovered Exchanges will be moved. If this option is
 used then the `maximumRedeliveries` option must also be provided.
+
+|`deserializationFilter` |String |A deserialization filter used when
+deserializing exchange data from the LevelDB store. The filter uses the
+standard Java `ObjectInputFilter` pattern syntax. By default, the filter
+is set to `java.**;org.apache.camel.**;!*` which allows Java platform
+classes and Apache Camel classes. If your application stores custom objects,
+you can adjust this filter to include additional packages
+(e.g., `java.**;org.apache.camel.**;com.mycompany.**;!*`).
 |=======================================================================
 
 The `repositoryName` option must be provided. Then either the
diff --git 
a/components/camel-leveldb/src/main/java/org/apache/camel/component/leveldb/LevelDBAggregationRepository.java
 
b/components/camel-leveldb/src/main/java/org/apache/camel/component/leveldb/LevelDBAggregationRepository.java
index e31372a57949..fed5c0dffb60 100644
--- 
a/components/camel-leveldb/src/main/java/org/apache/camel/component/leveldb/LevelDBAggregationRepository.java
+++ 
b/components/camel-leveldb/src/main/java/org/apache/camel/component/leveldb/LevelDBAggregationRepository.java
@@ -78,6 +78,20 @@ public class LevelDBAggregationRepository extends 
ServiceSupport implements Reco
               description = "To use a custom serializer for LevelDB")
     private LevelDBSerializer serializer;
 
+    /**
+     * Sets a deserialization filter while reading Object from Aggregation 
Repository. By default the filter will allow
+     * all java packages and subpackages and all org.apache.camel packages and 
subpackages, while the remaining will be
+     * blacklisted and not deserialized. This parameter should be customized 
if you're using classes you trust to be
+     * deserialized.
+     */
+    @Metadata(label = "advanced",
+              description = "Sets a deserialization filter while reading 
Object from Aggregation Repository."
+                            + " By default the filter will allow all java 
packages and subpackages and all org.apache.camel packages and subpackages,"
+                            + " while the remaining will be blacklisted and 
not deserialized."
+                            + " This parameter should be customized if you're 
using classes you trust to be deserialized.",
+              defaultValue = "java.**;org.apache.camel.**;!*")
+    private String deserializationFilter = "java.**;org.apache.camel.**;!*";
+
     /**
      * Creates an aggregation repository
      */
@@ -142,9 +156,9 @@ public class LevelDBAggregationRepository extends 
ServiceSupport implements Reco
 
             // only return old exchange if enabled
             if (isReturnOldExchange()) {
-                return codec().unmarshallExchange(camelContext, rc);
+                return codec().unmarshallExchange(camelContext, rc, 
deserializationFilter);
             }
-        } catch (IOException e) {
+        } catch (IOException | ClassNotFoundException e) {
             throw new RuntimeCamelException("Error adding to repository " + 
repositoryName + " with key " + key, e);
         }
 
@@ -161,9 +175,9 @@ public class LevelDBAggregationRepository extends 
ServiceSupport implements Reco
             byte[] rc = levelDBFile.getDb().get(lDbKey);
 
             if (rc != null) {
-                answer = codec().unmarshallExchange(camelContext, rc);
+                answer = codec().unmarshallExchange(camelContext, rc, 
deserializationFilter);
             }
-        } catch (IOException e) {
+        } catch (IOException | ClassNotFoundException e) {
             throw new RuntimeCamelException("Error getting key " + key + " 
from repository " + repositoryName, e);
         }
 
@@ -308,9 +322,9 @@ public class LevelDBAggregationRepository extends 
ServiceSupport implements Reco
             byte[] rc = levelDBFile.getDb().get(completedLDBKey);
 
             if (rc != null) {
-                answer = codec().unmarshallExchange(camelContext, rc);
+                answer = codec().unmarshallExchange(camelContext, rc, 
deserializationFilter);
             }
-        } catch (IOException e) {
+        } catch (IOException | ClassNotFoundException e) {
             throw new RuntimeCamelException(
                     "Error recovering exchangeId " + exchangeId + " from 
repository " + repositoryName, e);
         }
@@ -496,6 +510,14 @@ public class LevelDBAggregationRepository extends 
ServiceSupport implements Reco
         this.serializer = serializer;
     }
 
+    public String getDeserializationFilter() {
+        return deserializationFilter;
+    }
+
+    public void setDeserializationFilter(String deserializationFilter) {
+        this.deserializationFilter = deserializationFilter;
+    }
+
     public LevelDBCamelCodec codec() {
         if (codec == null) {
             codec = new LevelDBCamelCodec(serializer);
diff --git 
a/components/camel-leveldb/src/main/java/org/apache/camel/component/leveldb/LevelDBCamelCodec.java
 
b/components/camel-leveldb/src/main/java/org/apache/camel/component/leveldb/LevelDBCamelCodec.java
index a468c0fd0a50..72ac3c50840b 100644
--- 
a/components/camel-leveldb/src/main/java/org/apache/camel/component/leveldb/LevelDBCamelCodec.java
+++ 
b/components/camel-leveldb/src/main/java/org/apache/camel/component/leveldb/LevelDBCamelCodec.java
@@ -62,4 +62,19 @@ public final class LevelDBCamelCodec {
         }
         return answer;
     }
+
+    public Exchange unmarshallExchange(CamelContext camelContext, byte[] 
buffer, String deserializationFilter)
+            throws IOException, ClassNotFoundException {
+        Exchange answer = serializer.deserializeExchange(camelContext, buffer, 
deserializationFilter);
+
+        // restore the from endpoint
+        String fromEndpointUri = (String) 
answer.removeProperty("CamelAggregatedFromEndpoint");
+        if (fromEndpointUri != null) {
+            Endpoint fromEndpoint = camelContext.hasEndpoint(fromEndpointUri);
+            if (fromEndpoint != null) {
+                answer.getExchangeExtension().setFromEndpoint(fromEndpoint);
+            }
+        }
+        return answer;
+    }
 }
diff --git 
a/components/camel-leveldb/src/main/java/org/apache/camel/component/leveldb/LevelDBSerializer.java
 
b/components/camel-leveldb/src/main/java/org/apache/camel/component/leveldb/LevelDBSerializer.java
index 8b6bbc6e124f..6cffe4aec4f2 100644
--- 
a/components/camel-leveldb/src/main/java/org/apache/camel/component/leveldb/LevelDBSerializer.java
+++ 
b/components/camel-leveldb/src/main/java/org/apache/camel/component/leveldb/LevelDBSerializer.java
@@ -31,4 +31,22 @@ public interface LevelDBSerializer {
             throws IOException;
 
     Exchange deserializeExchange(CamelContext camelContext, byte[] buffer) 
throws IOException;
+
+    /**
+     * Deserializes an exchange from a byte buffer with a deserialization 
filter for security.
+     *
+     * @param  camelContext           the CamelContext
+     * @param  buffer                 the byte buffer containing serialized 
exchange data
+     * @param  deserializationFilter  the deserialization filter pattern to 
apply (e.g.,
+     *                                "java.**;org.apache.camel.**;!*")
+     * @return                        the deserialized Exchange
+     * @throws IOException            if an I/O error occurs
+     * @throws ClassNotFoundException if a class cannot be found during 
deserialization
+     */
+    default Exchange deserializeExchange(CamelContext camelContext, byte[] 
buffer, String deserializationFilter)
+            throws IOException, ClassNotFoundException {
+        // Default implementation for backward compatibility - delegates to 
the original method
+        // Subclasses should override this to apply the filter
+        return deserializeExchange(camelContext, buffer);
+    }
 }
diff --git 
a/components/camel-leveldb/src/main/java/org/apache/camel/component/leveldb/serializer/DefaultLevelDBSerializer.java
 
b/components/camel-leveldb/src/main/java/org/apache/camel/component/leveldb/serializer/DefaultLevelDBSerializer.java
index 1bf227527215..723a5859a65d 100644
--- 
a/components/camel-leveldb/src/main/java/org/apache/camel/component/leveldb/serializer/DefaultLevelDBSerializer.java
+++ 
b/components/camel-leveldb/src/main/java/org/apache/camel/component/leveldb/serializer/DefaultLevelDBSerializer.java
@@ -19,12 +19,14 @@ package org.apache.camel.component.leveldb.serializer;
 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 org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.support.DefaultExchangeHolder;
+import org.apache.camel.util.ClassLoadingAwareObjectInputStream;
 
 public class DefaultLevelDBSerializer extends AbstractLevelDBSerializer {
 
@@ -70,4 +72,20 @@ public class DefaultLevelDBSerializer extends 
AbstractLevelDBSerializer {
             }
         });
     }
+
+    @Override
+    public Exchange deserializeExchange(CamelContext camelContext, byte[] 
buffer, String deserializationFilter)
+            throws IOException, ClassNotFoundException {
+        return deserializeExchange(camelContext, buffer, b -> {
+            ClassLoader classLoader = 
camelContext.getApplicationContextClassLoader();
+            try (final ObjectInputStream ois = new 
ClassLoadingAwareObjectInputStream(
+                    classLoader,
+                    new ByteArrayInputStream(buffer))) {
+                
ois.setObjectInputFilter(ObjectInputFilter.Config.createFilter(deserializationFilter));
+                return (DefaultExchangeHolder) ois.readObject();
+            } catch (ClassNotFoundException e) {
+                throw new IOException("Failed to deserialize exchange", e);
+            }
+        });
+    }
 }

Reply via email to