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

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


The following commit(s) were added to refs/heads/main by this push:
     new 7f4cb4e3b76 Disable JMS ObjectMessage deserialization by default 
(#3337)
7f4cb4e3b76 is described below

commit 7f4cb4e3b765e632216fb7fc8acfa2c64e2179bf
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Mon Jul 27 15:34:19 2026 +0100

    Disable JMS ObjectMessage deserialization by default (#3337)
---
 .../org/apache/cxf/transport/jms/JMSConduit.java   |  3 +-
 .../apache/cxf/transport/jms/JMSConfigFactory.java |  2 +
 .../apache/cxf/transport/jms/JMSConfiguration.java | 29 ++++++++++++
 .../apache/cxf/transport/jms/JMSDestination.java   |  4 +-
 .../apache/cxf/transport/jms/JMSMessageUtils.java  | 15 ++++--
 .../apache/cxf/transport/jms/uri/JMSEndpoint.java  | 26 ++++++++++
 .../transport/jms/util/JMSMessageConverter.java    | 13 +++++
 .../cxf/transport/jms/JMSConfigFactoryTest.java    | 14 ++++++
 .../cxf/transport/jms/uri/JMSEndpointTest.java     | 24 ++++++++++
 .../jms/util/JMSMessageConverterTest.java          | 55 ++++++++++++++++++++++
 .../apache/cxf/transport/jms/util/JMSUtilTest.java | 11 +++--
 11 files changed, 187 insertions(+), 9 deletions(-)

diff --git 
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConduit.java 
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConduit.java
index 41d3377a72d..4f8db4a28cb 100644
--- 
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConduit.java
+++ 
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConduit.java
@@ -472,7 +472,8 @@ public class JMSConduit extends AbstractConduit implements 
JMSExchangeSender, Me
         LOG.log(Level.FINE, "client received reply: ", jmsMessage);
         try {
             Message inMessage = JMSMessageUtils.asCXFMessage(jmsMessage,
-                                                             
JMSConstants.JMS_CLIENT_RESPONSE_HEADERS);
+                                                             
JMSConstants.JMS_CLIENT_RESPONSE_HEADERS,
+                                                             
jmsConfig.isAllowObjectMessages());
             if (jmsConfig.isCreateSecurityContext()) {
                 SecurityContext securityContext = 
SecurityContextFactory.buildSecurityContext(jmsMessage, jmsConfig);
                 inMessage.put(SecurityContext.class, securityContext);
diff --git 
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConfigFactory.java
 
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConfigFactory.java
index 5a95b40d406..2cfe46df416 100644
--- 
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConfigFactory.java
+++ 
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConfigFactory.java
@@ -83,6 +83,8 @@ public final class JMSConfigFactory {
         jmsConfig.setConcurrentConsumers(endpoint.getConcurrentConsumers());
         
jmsConfig.setOneSessionPerConnection(endpoint.isOneSessionPerConnection());
         jmsConfig.setMessageSelector(endpoint.getMessageSelector());
+        
jmsConfig.setUseObjectMessageFallback(endpoint.isUseObjectMessageFallback());
+        jmsConfig.setAllowObjectMessages(endpoint.isAllowObjectMessages());
 
         TransactionManager tm = getTransactionManager(bus, endpoint);
         jmsConfig.setTransactionManager(tm);
diff --git 
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConfiguration.java
 
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConfiguration.java
index b72a111885d..e6cbb9da07f 100644
--- 
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConfiguration.java
+++ 
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConfiguration.java
@@ -87,7 +87,16 @@ public class JMSConfiguration {
     private volatile Destination replyToDestinationDest;
 
     private String messageType = JMSConstants.TEXT_MESSAGE_TYPE;
+    /**
+     * Outbound only: when true, non-text payloads may fall back to 
ObjectMessage.
+     * When false, non-text payloads are sent as BytesMessage.
+     */
     private boolean useObjectMessageFallback;
+    /**
+     * Inbound only: when true, ObjectMessage deserialization is allowed.
+     * When false, inbound ObjectMessage is rejected.
+     */
+    private boolean allowObjectMessages;
     private boolean pubSubDomain;
     private boolean replyPubSubDomain;
 
@@ -285,14 +294,34 @@ public class JMSConfiguration {
         this.messageType = messageType;
     }
 
+    /**
+     * Outbound only: controls ObjectMessage fallback in payload creation.
+     */
     public boolean isUseObjectMessageFallback() {
         return useObjectMessageFallback;
     }
 
+    /**
+     * Outbound only: controls ObjectMessage fallback in payload creation.
+     */
     public void setUseObjectMessageFallback(boolean useObjectMessageFallback) {
         this.useObjectMessageFallback = useObjectMessageFallback;
     }
 
+    /**
+     * Inbound only: controls whether ObjectMessage deserialization is 
permitted.
+     */
+    public boolean isAllowObjectMessages() {
+        return allowObjectMessages;
+    }
+
+    /**
+     * Inbound only: controls whether ObjectMessage deserialization is 
permitted.
+     */
+    public void setAllowObjectMessages(boolean allowObjectMessages) {
+        this.allowObjectMessages = allowObjectMessages;
+    }
+
     public boolean isPubSubDomain() {
         return pubSubDomain;
     }
diff --git 
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSDestination.java
 
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSDestination.java
index 1430d80f9f7..a54c265afe3 100644
--- 
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSDestination.java
+++ 
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSDestination.java
@@ -228,7 +228,9 @@ public class JMSDestination extends 
AbstractMultiplexDestination implements Mess
             getLogger().log(Level.FINE,
                             "JMS destination received message " + message + " 
on "
                                 + jmsConfig.getTargetDestination());
-            Message inMessage = JMSMessageUtils.asCXFMessage(message, 
JMSConstants.JMS_SERVER_REQUEST_HEADERS);
+            Message inMessage = JMSMessageUtils.asCXFMessage(message,
+                                                             
JMSConstants.JMS_SERVER_REQUEST_HEADERS,
+                                                             
jmsConfig.isAllowObjectMessages());
             if (jmsConfig.isCreateSecurityContext()) {
                 SecurityContext securityContext = 
SecurityContextFactory.buildSecurityContext(message, jmsConfig);
                 inMessage.put(SecurityContext.class, securityContext);
diff --git 
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSMessageUtils.java
 
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSMessageUtils.java
index 5e28ebbad4c..4a5c80232c2 100644
--- 
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSMessageUtils.java
+++ 
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSMessageUtils.java
@@ -58,11 +58,18 @@ final class JMSMessageUtils {
     }
     public static org.apache.cxf.message.Message asCXFMessage(Message message, 
String jmsHeadersKey)
         throws UnsupportedEncodingException, JMSException {
+        return asCXFMessage(message, jmsHeadersKey, false);
+    }
+
+    public static org.apache.cxf.message.Message asCXFMessage(Message message,
+                                                              String 
jmsHeadersKey,
+                                                              boolean 
allowObjectMessage)
+        throws UnsupportedEncodingException, JMSException {
         org.apache.cxf.message.Message inMessage = new MessageImpl();
         JMSMessageHeadersType messageHeaders = 
JMSMessageHeadersType.from(message);
         inMessage.put(jmsHeadersKey, messageHeaders);
         populateIncomingContext(messageHeaders, inMessage);
-        retrieveAndSetPayload(inMessage, message);
+        retrieveAndSetPayload(inMessage, message, allowObjectMessage);
         return inMessage;
     }
 
@@ -74,10 +81,12 @@ final class JMSMessageUtils {
      * @throws UnsupportedEncodingException
      * @throws JMSException
      */
-    private static void retrieveAndSetPayload(org.apache.cxf.message.Message 
inMessage, Message message)
+    private static void retrieveAndSetPayload(org.apache.cxf.message.Message 
inMessage,
+                                              Message message,
+                                              boolean allowObjectMessage)
         throws UnsupportedEncodingException, JMSException {
         final String messageType;
-        Object converted = new JMSMessageConverter().fromMessage(message);
+        Object converted = new 
JMSMessageConverter(allowObjectMessage).fromMessage(message);
         if (converted instanceof String) {
             inMessage.setContent(Reader.class, new 
StringReader((String)converted));
             messageType = JMSConstants.TEXT_MESSAGE_TYPE;
diff --git 
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/uri/JMSEndpoint.java
 
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/uri/JMSEndpoint.java
index a05571d67ac..886e5317a95 100644
--- 
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/uri/JMSEndpoint.java
+++ 
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/uri/JMSEndpoint.java
@@ -89,6 +89,8 @@ public class JMSEndpoint {
     private int retryInterval = 5000;
     private boolean oneSessionPerConnection;
     private boolean ignoreTimeoutException;
+    private boolean useObjectMessageFallback;
+    private boolean allowObjectMessages;
 
     /**
      * @param endpointUri
@@ -517,4 +519,28 @@ public class JMSEndpoint {
         this.ignoreTimeoutException = ignoreTimeoutException;
     }
 
+    public boolean isAllowObjectMessages() {
+        return allowObjectMessages;
+    }
+
+    public void setAllowObjectMessages(boolean allowObjectMessages) {
+        this.allowObjectMessages = allowObjectMessages;
+    }
+
+    public void setAllowObjectMessages(String allowObjectMessages) {
+        this.allowObjectMessages = Boolean.parseBoolean(allowObjectMessages);
+    }
+
+    public boolean isUseObjectMessageFallback() {
+        return useObjectMessageFallback;
+    }
+
+    public void setUseObjectMessageFallback(boolean useObjectMessageFallback) {
+        this.useObjectMessageFallback = useObjectMessageFallback;
+    }
+
+    public void setUseObjectMessageFallback(String useObjectMessageFallback) {
+        this.useObjectMessageFallback = 
Boolean.parseBoolean(useObjectMessageFallback);
+    }
+
 }
diff --git 
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/util/JMSMessageConverter.java
 
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/util/JMSMessageConverter.java
index c25287366a7..9744fefac5e 100644
--- 
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/util/JMSMessageConverter.java
+++ 
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/util/JMSMessageConverter.java
@@ -37,6 +37,16 @@ import jakarta.jms.TextMessage;
  */
 public class JMSMessageConverter {
 
+    private final boolean allowObjectMessage;
+
+    public JMSMessageConverter() {
+        this(false);
+    }
+
+    public JMSMessageConverter(boolean allowObjectMessage) {
+        this.allowObjectMessage = allowObjectMessage;
+    }
+
     public Message toMessage(Object object, Session session) throws 
JMSException {
         if (object instanceof Message) {
             return (Message)object;
@@ -67,6 +77,9 @@ public class JMSMessageConverter {
             message1.readBytes(bytes);
             return bytes;
         } else if (message instanceof ObjectMessage) {
+            if (!allowObjectMessage) {
+                throw new JMSException("ObjectMessage is disabled by 
configuration");
+            }
             return ((ObjectMessage)message).getObject();
         } else if (message instanceof StreamMessage) {
             StreamMessage streamMessage = (StreamMessage)message;
diff --git 
a/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/JMSConfigFactoryTest.java
 
b/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/JMSConfigFactoryTest.java
index 0c4af03be86..ffcdca0a119 100644
--- 
a/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/JMSConfigFactoryTest.java
+++ 
b/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/JMSConfigFactoryTest.java
@@ -136,4 +136,18 @@ public class JMSConfigFactoryTest extends 
AbstractJMSTester {
         JMSConfiguration config = JMSConfigFactory.createFromEndpointInfo(bus, 
ei, null);
         Assert.assertEquals("customJMSAttribute=helloWorld", 
config.getMessageSelector());
     }
+
+    @Test
+    public void testUseObjectMessageFallbackIsSet() {
+        JMSEndpoint endpoint = new 
JMSEndpoint("jms:queue:Foo.Bar?useObjectMessageFallback=true");
+        JMSConfiguration jmsConfig = JMSConfigFactory.createFromEndpoint(bus, 
endpoint);
+        Assert.assertTrue(jmsConfig.isUseObjectMessageFallback());
+    }
+
+    @Test
+    public void testAllowObjectMessagesIsSet() {
+        JMSEndpoint endpoint = new 
JMSEndpoint("jms:queue:Foo.Bar?allowObjectMessages=true");
+        JMSConfiguration jmsConfig = JMSConfigFactory.createFromEndpoint(bus, 
endpoint);
+        Assert.assertTrue(jmsConfig.isAllowObjectMessages());
+    }
 }
diff --git 
a/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/uri/JMSEndpointTest.java
 
b/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/uri/JMSEndpointTest.java
index bc9b4400929..158d81633fa 100644
--- 
a/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/uri/JMSEndpointTest.java
+++ 
b/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/uri/JMSEndpointTest.java
@@ -190,6 +190,30 @@ public class JMSEndpointTest {
 
     }
 
+    @Test
+    public void testAllowObjectMessagesDefaultsToFalse() {
+        JMSEndpoint endpoint = new JMSEndpoint("jms:queue:Foo.Bar");
+        assertFalse(endpoint.isAllowObjectMessages());
+    }
+
+    @Test
+    public void testAllowObjectMessagesCanBeEnabledFromUri() {
+        JMSEndpoint endpoint = new 
JMSEndpoint("jms:queue:Foo.Bar?allowObjectMessages=true");
+        assertTrue(endpoint.isAllowObjectMessages());
+    }
+
+    @Test
+    public void testUseObjectMessageFallbackDefaultsToFalse() {
+        JMSEndpoint endpoint = new JMSEndpoint("jms:queue:Foo.Bar");
+        assertFalse(endpoint.isUseObjectMessageFallback());
+    }
+
+    @Test
+    public void testUseObjectMessageFallbackCanBeEnabledFromUri() {
+        JMSEndpoint endpoint = new 
JMSEndpoint("jms:queue:Foo.Bar?useObjectMessageFallback=true");
+        assertTrue(endpoint.isUseObjectMessageFallback());
+    }
+
     @Test
     public void nonSoapJMS() throws Exception {
         JMSEndpoint endpoint = new JMSEndpoint("jms://");
diff --git 
a/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/util/JMSMessageConverterTest.java
 
b/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/util/JMSMessageConverterTest.java
new file mode 100644
index 00000000000..8e08d33d17a
--- /dev/null
+++ 
b/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/util/JMSMessageConverterTest.java
@@ -0,0 +1,55 @@
+/**
+ * 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 org.apache.cxf.transport.jms.util;
+
+import jakarta.jms.JMSException;
+import jakarta.jms.ObjectMessage;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class JMSMessageConverterTest {
+
+    @Test
+    public void testObjectMessageIsRejectedByDefault() throws Exception {
+        JMSMessageConverter converter = new JMSMessageConverter();
+        ObjectMessage objectMessage = mock(ObjectMessage.class);
+
+        try {
+            converter.fromMessage(objectMessage);
+            fail("Expected JMSException to be thrown");
+        } catch (JMSException ex) {
+            assertEquals("ObjectMessage is disabled by configuration", 
ex.getMessage());
+        }
+    }
+
+    @Test
+    public void testObjectMessageCanBeEnabled() throws Exception {
+        JMSMessageConverter converter = new JMSMessageConverter(true);
+        ObjectMessage objectMessage = mock(ObjectMessage.class);
+        when(objectMessage.getObject()).thenReturn("payload");
+
+        Object payload = converter.fromMessage(objectMessage);
+        assertEquals("payload", payload);
+    }
+}
diff --git 
a/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/util/JMSUtilTest.java
 
b/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/util/JMSUtilTest.java
index 5345b9bf540..b66ed47ddeb 100644
--- 
a/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/util/JMSUtilTest.java
+++ 
b/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/util/JMSUtilTest.java
@@ -83,14 +83,17 @@ public class JMSUtilTest {
             Connection connection = JMSFactory.createConnection(jmsConfig);
             Session session = connection.createSession(false, 
Session.AUTO_ACKNOWLEDGE);
             jakarta.jms.Message jmsMessage =
-                JMSUtil.createAndSetPayload(testBytes, session, 
JMSConstants.BYTE_MESSAGE_TYPE);
+                JMSUtil.createAndSetPayload(testBytes, session, 
JMSConstants.BYTE_MESSAGE_TYPE, false);
             assertTrue("Message should have been of type BytesMessage ", 
jmsMessage instanceof BytesMessage);
-            jmsMessage = JMSUtil.createAndSetPayload(testBytes, session, 
JMSConstants.BINARY_MESSAGE_TYPE);
-            assertTrue("Binary message fallback should have been of type 
ObjectMessage ",
-                       jmsMessage instanceof ObjectMessage);
+            jmsMessage = JMSUtil.createAndSetPayload(testBytes, session, 
JMSConstants.BINARY_MESSAGE_TYPE, false);
+            assertTrue("Default binary message should have been of type 
BytesMessage ",
+                       jmsMessage instanceof BytesMessage);
             jmsMessage = JMSUtil.createAndSetPayload(testBytes, session, 
JMSConstants.BINARY_MESSAGE_TYPE, false);
             assertTrue("Fallback-disabled binary message should have been of 
type BytesMessage ",
                        jmsMessage instanceof BytesMessage);
+            jmsMessage = JMSUtil.createAndSetPayload(testBytes, session, 
JMSConstants.BINARY_MESSAGE_TYPE, true);
+            assertTrue("Fallback-enabled binary message should have been of 
type ObjectMessage ",
+                       jmsMessage instanceof ObjectMessage);
             jmsMessage = JMSUtil.createAndSetPayload(testBytes, session, 
"application/octet-stream", true);
             assertTrue("Non-text message fallback should have been of type 
ObjectMessage ",
                        jmsMessage instanceof ObjectMessage);

Reply via email to