From df4190bec88b0a9699950b9fc1bc913b423d1b4f Mon Sep 17 00:00:00 2001 From: Andrea Cosentino Date: Mon, 13 Apr 2026 15:15:24 +0200 Subject: [PATCH] CAMEL-23319: Add deserialization filtering to camel-mina converter - MinaConverter.toObjectInput(): Apply default ObjectInputFilter restricting to java.**, javax.**, org.apache.camel.** (respects JVM-wide filter if set) Signed-off-by: Andrea Cosentino --- .../camel/component/mina/MinaConverter.java | 21 ++++++++++- .../external/NotAllowedSerializable.java | 37 +++++++++++++++++++ .../component/mina/MinaConverterTest.java | 33 +++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 components/camel-mina/src/test/java/com/example/external/NotAllowedSerializable.java diff --git a/components/camel-mina/src/main/java/org/apache/camel/component/mina/MinaConverter.java b/components/camel-mina/src/main/java/org/apache/camel/component/mina/MinaConverter.java index d34f6309ade58..3c55670e07c69 100644 --- a/components/camel-mina/src/main/java/org/apache/camel/component/mina/MinaConverter.java +++ b/components/camel-mina/src/main/java/org/apache/camel/component/mina/MinaConverter.java @@ -19,18 +19,28 @@ import java.io.IOException; import java.io.InputStream; import java.io.ObjectInput; +import java.io.ObjectInputFilter; import java.io.ObjectInputStream; import org.apache.camel.Converter; import org.apache.camel.Exchange; import org.apache.camel.StreamCache; import org.apache.mina.core.buffer.IoBuffer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * A set of converter methods for working with MINA types */ @Converter(generateLoader = true) public final class MinaConverter { + private static final Logger LOG = LoggerFactory.getLogger(MinaConverter.class); + + /** + * Default deserialization filter that restricts which classes can be deserialized. Allows standard Java types and + * Apache Camel types. Can be overridden via the JVM system property {@code jdk.serialFilter}. + */ + static final String DEFAULT_DESERIALIZATION_FILTER = "java.**;javax.**;org.apache.camel.**;!*"; private MinaConverter() { //Utility Class @@ -59,7 +69,16 @@ public static InputStream toInputStream(IoBuffer buffer) { @Converter public static ObjectInput toObjectInput(IoBuffer buffer) throws IOException { InputStream is = toInputStream(buffer); - return new ObjectInputStream(is); + ObjectInputStream ois = new ObjectInputStream(is); + ObjectInputFilter jvmFilter = ObjectInputFilter.Config.getSerialFilter(); + if (jvmFilter != null) { + ois.setObjectInputFilter(jvmFilter); + } else { + LOG.debug("No JVM-wide deserialization filter set, applying default Camel filter: {}", + DEFAULT_DESERIALIZATION_FILTER); + ois.setObjectInputFilter(ObjectInputFilter.Config.createFilter(DEFAULT_DESERIALIZATION_FILTER)); + } + return ois; } @Converter diff --git a/components/camel-mina/src/test/java/com/example/external/NotAllowedSerializable.java b/components/camel-mina/src/test/java/com/example/external/NotAllowedSerializable.java new file mode 100644 index 0000000000000..204d84216745b --- /dev/null +++ b/components/camel-mina/src/test/java/com/example/external/NotAllowedSerializable.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.example.external; + +import java.io.Serializable; + +/** + * Serializable type living outside the {@code java.**}, {@code javax.**} and {@code org.apache.camel.**} packages, used + * to verify that the default deserialization allowlist rejects unknown classes. + */ +public final class NotAllowedSerializable implements Serializable { + private static final long serialVersionUID = 1L; + + private final String value; + + public NotAllowedSerializable(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/components/camel-mina/src/test/java/org/apache/camel/component/mina/MinaConverterTest.java b/components/camel-mina/src/test/java/org/apache/camel/component/mina/MinaConverterTest.java index ed12049bff0be..8b3060b97b1ee 100644 --- a/components/camel-mina/src/test/java/org/apache/camel/component/mina/MinaConverterTest.java +++ b/components/camel-mina/src/test/java/org/apache/camel/component/mina/MinaConverterTest.java @@ -16,10 +16,15 @@ */ package org.apache.camel.component.mina; +import java.io.ByteArrayOutputStream; import java.io.InputStream; +import java.io.InvalidClassException; +import java.io.ObjectInput; +import java.io.ObjectOutputStream; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; +import com.example.external.NotAllowedSerializable; import org.apache.camel.Exchange; import org.apache.camel.impl.DefaultCamelContext; import org.apache.camel.support.DefaultExchange; @@ -27,7 +32,9 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; public class MinaConverterTest { @@ -97,4 +104,30 @@ public void testToByteBuffer() { assertEquals(in[i], out[i]); } } + + @Test + public void testToObjectInputAcceptsAllowlistedTypes() throws Exception { + IoBuffer bb = serialize("hello"); + try (ObjectInput in = MinaConverter.toObjectInput(bb)) { + Object value = in.readObject(); + assertInstanceOf(String.class, value); + assertEquals("hello", value); + } + } + + @Test + public void testToObjectInputRejectsUnlistedTypes() throws Exception { + IoBuffer bb = serialize(new NotAllowedSerializable("blocked")); + try (ObjectInput in = MinaConverter.toObjectInput(bb)) { + assertThrows(InvalidClassException.class, in::readObject); + } + } + + private static IoBuffer serialize(Object value) throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { + oos.writeObject(value); + } + return IoBuffer.wrap(baos.toByteArray()); + } }