This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch camel-4.14.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-4.14.x by this push:
new 59a8f5d07a42 CAMEL-22966 - Camel-LevelDB: Add ObjectInputFilter String
pattern par… (#21289)
59a8f5d07a42 is described below
commit 59a8f5d07a4261c8c4313aae86ebb2b4f6070f6c
Author: Andrea Cosentino <[email protected]>
AuthorDate: Fri Feb 6 14:46:14 2026 +0100
CAMEL-22966 - Camel-LevelDB: Add ObjectInputFilter String pattern par…
(#21289)
* CAMEL-22966 - Camel-LevelDB: Add ObjectInputFilter String pattern
parameter in LevelDBAggregationRepository to be used in unmarshall operations
Signed-off-by: Andrea Cosentino <[email protected]>
* CAMEL-22966 - Camel-LevelDB: Add ObjectInputFilter String pattern
parameter in LevelDBAggregationRepository to be used in unmarshall operations
Signed-off-by: Andrea Cosentino <[email protected]>
---------
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 dbb9bb84be7d..0e03e18ef95e 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.14.5-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 dbb9bb84be7d..0e03e18ef95e 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.14.5-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);
+ }
+ });
+ }
}