//nefariousplan

CVE-2026-40453: Camel Patched One Header Filter In 2025. Five More Needed The Same Line.

pattern

cve

proof of concept

The patch for CVE-2025-27636 was one line. setLowerCase(true);, added to HttpHeaderFilterStrategy.initialize() in March 2025. Apache Camel ships six classes that extend DefaultHeaderFilterStrategy and apply it to inbound headers. The 2025 patch added the line to one. CVE-2026-40453 is the maintainer adding the same line to the other five, thirteen months later.

The 2025 bypass was case-variant headers

Akamai's PoC for CVE-2025-27636 is a vulnerable Camel app with one route:

from("jetty:http://0.0.0.0:80/vulnerable")
    .log("Received request from client")
    // define a static command. This can be overwritten using the "CamelExecCommandExecutable" header
    .to("exec:whoami")
    .convertBodyTo(String.class)
    .log("Command Output: ${body}");

The route consumes HTTP requests on port 80 and routes the exchange to camel-exec, which runs the static command whoami. The exec binding overrides that static command if the exchange carries a header named CamelExecCommandExecutable. This is documented behaviour of the component.

The default header filter strategy for HTTP-based components blocks any incoming header whose name starts with Camel, camel, or org.apache.camel.. That filter would catch CamelExecCommandExecutable and stop the override. The bypass is to send the header with case the prefix list does not contain:

$ curl "http://localhost:80/vulnerable" --header "CAmelExecCommandExecutable: ls"
pom.xml
src
target

CAmelExecCommandExecutable starts with the bytes CA. None of Camel, camel, or org.apache.camel. start with CA. The filter passes the header through. Camel's internal header storage is a CaseInsensitiveMap, so once past the filter, the exec component reads the value back through the canonical header name and runs ls instead of whoami.

The 2025 fix added setLowerCase(true) to one class

Claus Ibsen's CAMEL-21828, dated March 4 2025, lands one line in HttpHeaderFilterStrategy:

public class HttpHeaderFilterStrategy extends DefaultHeaderFilterStrategy {

    public HttpHeaderFilterStrategy() {
        initialize();
    }

    protected void initialize() {
        final Set<String> outFilter = getOutFilter();
        HttpUtil.addCommonFilters(outFilter);

        setLowerCase(true);

        // filter headers begin with "Camel" or "org.apache.camel"
        // must ignore case for Http based transports
        setOutFilterStartsWith(CAMEL_FILTER_STARTS_WITH);
        setInFilterStartsWith(CAMEL_FILTER_STARTS_WITH);
    }
}

setLowerCase(true) flips a flag on the parent class. With the flag set, the filter checks headerName.toLowerCase() against the prefix list as well as the original casing. "CAmelExecCommandExecutable".toLowerCase() starts with camel. The bypass closes.

The flag lives on the parent.

DefaultHeaderFilterStrategy ships lowerCase=false

DefaultHeaderFilterStrategy is the base every Camel header filter strategy extends. The field declaration:

@Metadata(label = "advanced", defaultValue = "false",
          description = "Whether header names should be converted to lower case before checking it with the filter Set."
                        + " It does not affect filtering using regular expression pattern.")
private boolean lowerCase;

The metadata documents defaultValue = "false". Subclasses that want case-insensitive prefix matching must call setLowerCase(true) themselves. The 2025 patch added one such call. HttpHeaderFilterStrategy is one subclass. It is not the only subclass applied to inbound headers from a network-reachable transport.

Five other subclasses configured the prefix list and omitted the lowercase flag

JmsHeaderFilterStrategy, post-2025-patch and pre-2026-patch:

public class JmsHeaderFilterStrategy extends DefaultHeaderFilterStrategy {

    public JmsHeaderFilterStrategy() {
        this(false);
    }

    public JmsHeaderFilterStrategy(boolean includeAllJMSXProperties) {
        setOutFilterStartsWith(DefaultHeaderFilterStrategy.CAMEL_FILTER_STARTS_WITH);
        setInFilterStartsWith(DefaultHeaderFilterStrategy.CAMEL_FILTER_STARTS_WITH);
        if (!includeAllJMSXProperties) {
            initialize();
        }
    }
    // ...
}

The constructor calls setOutFilterStartsWith and setInFilterStartsWith with the same CAMEL_FILTER_STARTS_WITH array HttpHeaderFilterStrategy uses. It does not call setLowerCase(true). The same CAmel-prefixed header that the 2025 patch closes for HTTP traffic continues to pass through the JMS filter unchanged.

SjmsHeaderFilterStrategy, CoAPHeaderFilterStrategy, and GooglePubsubHeaderFilterStrategy are structurally identical: they configure the prefix list, they omit the lowercase flag. ClassicJmsHeaderFilterStrategy (the legacy JMS shape kept for backwards compatibility) does not configure the prefix list at all, so any Camel-prefixed header passes through it regardless of case.

camel-exec, camel-file, and camel-bean read their behaviour-altering headers from the same CaseInsensitiveMap no matter which transport delivered them. The reachability is symmetric: any consumer route that passes JMS, SJMS, CoAP, or Google PubSub messages to those components is exploitable by an attacker with producer access to the broker.

The 2026 patch is the same one line in five files

Saroj Khadka reported CAMEL-23313. Andrea Cosentino's commit 3d2efeed2, dated April 13 2026, lands the fix:

$ git show 3d2efeed2 --stat
commit 3d2efeed2f6ea757f0254a1d1cdeb9a4f28ca147
Author: Andrea Cosentino <ancosen@gmail.com>
Date:   Mon Apr 13 10:22:39 2026 +0200

    CAMEL-23313: HeaderFilter Strategies - add lowerCase where it's not present
                 - JMS, SJMS, CoAP, Google PubSub (#22569)

 .../camel/coap/CoAPHeaderFilterStrategy.java                            | 1 +
 .../camel/component/google/pubsub/GooglePubsubHeaderFilterStrategy.java | 1 +
 .../camel/component/jms/ClassicJmsHeaderFilterStrategy.java             | 1 +
 .../camel/component/jms/JmsHeaderFilterStrategy.java                    | 1 +
 .../camel/component/sjms/SjmsHeaderFilterStrategy.java                  | 1 +
 5 files changed, 5 insertions(+)

The diff for each of the five files is the same one line:

 public JmsHeaderFilterStrategy(boolean includeAllJMSXProperties) {
+    setLowerCase(true);
     setOutFilterStartsWith(DefaultHeaderFilterStrategy.CAMEL_FILTER_STARTS_WITH);
     setInFilterStartsWith(DefaultHeaderFilterStrategy.CAMEL_FILTER_STARTS_WITH);
     if (!includeAllJMSXProperties) {
         initialize();
     }
 }

The five insertions, taken together, are byte-for-byte the same edit the original CVE-2025-27636 patch made to HttpHeaderFilterStrategy thirteen months earlier.

This is design-debt-driver. The five other vulnerable children were visible the day the substrate first produced the class.

This is a design-debt-driver. The bug class is the substrate's choice to make lowerCase opt-in for every subclass that filters Camel-prefixed headers from untrusted input. The 2025 patch closed the instance in HttpHeaderFilterStrategy. The substrate continued to produce the same bug class in the other five subclasses, every one of which the same project shipped, in the same monorepo, with the same constructor pattern of "configure the prefix list, do not opt into lowercase."

The Tomcat EncryptInterceptor exhibit on the same pattern shows the recurring shape: a security component generating consecutive CVEs from its primary security method because the architectural choice that produced the first CVE survives the patch. Camel's case is cleaner. The five other vulnerable subclasses were not new code introduced after the 2025 patch. They were sitting in the apache/camel tree, under components/camel-jms, components/camel-sjms, components/camel-coap, and components/camel-google/camel-google-pubsub, when the 2025 patch landed.

The CVE-2025-27636 vendor advisory listed twenty-two components as users of the default header filter strategy, including camel-jms and camel-sjms. The advisory's mitigation guidance read:

use the removeHeaders EIP, to filter out anything like "cAmel, cAMEL" etc, or in general everything not starting with "Camel", "camel" or "org.apache.camel."

The vendor documented the case-variant attack as an operator-side burden in March 2025. The patch closed that burden for HTTP traffic. The other transports kept the burden for thirteen months.

PoC: akamai/CVE-2025-27636-Apache-Camel-PoC

DefaultHeaderFilterStrategy.lowerCase still defaults to false in master. The next subclass that extends it and is used to filter inbound headers will inherit the same one-line patch waiting to be remembered.