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 e6e5621639a1 CAMEL-24655: camel-coap - guard case-insensitive header 
filtering
e6e5621639a1 is described below

commit e6e5621639a1e39540feb57d5f1b3687069ce565
Author: Andrea Cosentino <[email protected]>
AuthorDate: Tue Sep 8 20:11:24 2026 +0200

    CAMEL-24655: camel-coap - guard case-insensitive header filtering
    
    The CoAP consumer maps the URI query parameters of an incoming request
    into Exchange headers, running each through the endpoint
    HeaderFilterStrategy first. The default strategy filters names starting
    with Camel/camel case-insensitively, so a remote peer cannot set Camel
    internal headers that steer downstream processing. That behaviour was
    correct but untested, so a refactoring of the consumer could silently
    drop it - the exact regression the CVE-2025-27636 family was about.
    
    Adds CoAPHeaderInjectionTest: sends requests carrying a Camel internal
    header name as a URI query parameter in four casings and asserts it is
    never mapped onto the Exchange, while an ordinary query parameter still
    is. Verified to fail when the filter call in CamelCoapResource is
    removed. Test-only; no production code is modified.
    
    Closes #26208
    
    Co-authored-by: Claude Opus 5 <[email protected]>
---
 .../apache/camel/coap/CoAPHeaderInjectionTest.java | 83 ++++++++++++++++++++++
 1 file changed, 83 insertions(+)

diff --git 
a/components/camel-coap/src/test/java/org/apache/camel/coap/CoAPHeaderInjectionTest.java
 
b/components/camel-coap/src/test/java/org/apache/camel/coap/CoAPHeaderInjectionTest.java
new file mode 100644
index 000000000000..82a14c81ad15
--- /dev/null
+++ 
b/components/camel-coap/src/test/java/org/apache/camel/coap/CoAPHeaderInjectionTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.camel.coap;
+
+import java.util.List;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.eclipse.californium.core.CoapClient;
+import org.eclipse.californium.core.coap.MediaTypeRegistry;
+import org.eclipse.californium.core.coap.Request;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+/**
+ * The CoAP consumer maps URI query parameters of an incoming request into 
Exchange headers. A remote peer must not be
+ * able to use that to set Camel internal headers, whatever casing it uses, as 
those steer downstream processing (bean
+ * method dispatch, file names, and so on).
+ */
+public class CoAPHeaderInjectionTest extends CoAPTestSupport {
+
+    private static final String[] CAMEL_HEADER_VARIANTS = {
+            "CamelBeanMethodName", "camelBeanMethodName", 
"caMELBeanMethodName", "CAMELBEANMETHODNAME" };
+
+    @Test
+    void camelHeadersInUriQueryAreFilteredRegardlessOfCase() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(CAMEL_HEADER_VARIANTS.length);
+
+        CoapClient client = createClient("/TestResource");
+        for (String variant : CAMEL_HEADER_VARIANTS) {
+            Request request = Request.newPost();
+            request.setURI(client.getURI() + "?" + variant + 
"=malicious&normalParam=value");
+            request.setPayload("test");
+            
request.getOptions().setContentFormat(MediaTypeRegistry.TEXT_PLAIN);
+            assertNotNull(client.advanced(request), "no CoAP response received 
for variant " + variant);
+        }
+
+        MockEndpoint.assertIsSatisfied(context);
+
+        List<Exchange> received = mock.getReceivedExchanges();
+        for (int i = 0; i < CAMEL_HEADER_VARIANTS.length; i++) {
+            String variant = CAMEL_HEADER_VARIANTS[i];
+            Message in = received.get(i).getIn();
+            // the Camel header map is case-insensitive, so this lookup also 
catches the other spellings
+            assertNull(in.getHeader(variant),
+                    "a Camel internal header must not be injectable through a 
CoAP URI query parameter: " + variant);
+            assertEquals("value", in.getHeader("normalParam", String.class),
+                    "a non-Camel query parameter must still be mapped to a 
header");
+        }
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                fromF("coap://localhost:%d/TestResource", PORT.getPort())
+                        .to("mock:result")
+                        .setBody(constant("ok"));
+            }
+        };
+    }
+}

Reply via email to