-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 NEFARIOUSPLAN-CANONICAL-V1 {"body_md":"## The 2025 bypass was case-variant headers\n\nAkamai's [PoC for CVE-2025-27636](https://github.com/akamai/CVE-2025-27636-Apache-Camel-PoC) is a vulnerable Camel app with one route:\n\n```java\nfrom(\"jetty:http://0.0.0.0:80/vulnerable\")\n .log(\"Received request from client\")\n // define a static command. This can be overwritten using the \"CamelExecCommandExecutable\" header\n .to(\"exec:whoami\")\n .convertBodyTo(String.class)\n .log(\"Command Output: ${body}\");\n```\n\nThe 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.\n\nThe 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:\n\n```\n$ curl \"http://localhost:80/vulnerable\" --header \"CAmelExecCommandExecutable: ls\"\npom.xml\nsrc\ntarget\n```\n\n`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`.\n\n## The 2025 fix added setLowerCase(true) to one class\n\nClaus Ibsen's CAMEL-21828, dated March 4 2025, lands one line in `HttpHeaderFilterStrategy`:\n\n```java\npublic class HttpHeaderFilterStrategy extends DefaultHeaderFilterStrategy {\n\n public HttpHeaderFilterStrategy() {\n initialize();\n }\n\n protected void initialize() {\n final Set outFilter = getOutFilter();\n HttpUtil.addCommonFilters(outFilter);\n\n setLowerCase(true);\n\n // filter headers begin with \"Camel\" or \"org.apache.camel\"\n // must ignore case for Http based transports\n setOutFilterStartsWith(CAMEL_FILTER_STARTS_WITH);\n setInFilterStartsWith(CAMEL_FILTER_STARTS_WITH);\n }\n}\n```\n\n`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.\n\nThe flag lives on the parent.\n\n## DefaultHeaderFilterStrategy ships lowerCase=false\n\n`DefaultHeaderFilterStrategy` is the base every Camel header filter strategy extends. The field declaration:\n\n```java\n@Metadata(label = \"advanced\", defaultValue = \"false\",\n description = \"Whether header names should be converted to lower case before checking it with the filter Set.\"\n + \" It does not affect filtering using regular expression pattern.\")\nprivate boolean lowerCase;\n```\n\nThe 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.\n\n## Five other subclasses configured the prefix list and omitted the lowercase flag\n\n`JmsHeaderFilterStrategy`, post-2025-patch and pre-2026-patch:\n\n```java\npublic class JmsHeaderFilterStrategy extends DefaultHeaderFilterStrategy {\n\n public JmsHeaderFilterStrategy() {\n this(false);\n }\n\n public JmsHeaderFilterStrategy(boolean includeAllJMSXProperties) {\n setOutFilterStartsWith(DefaultHeaderFilterStrategy.CAMEL_FILTER_STARTS_WITH);\n setInFilterStartsWith(DefaultHeaderFilterStrategy.CAMEL_FILTER_STARTS_WITH);\n if (!includeAllJMSXProperties) {\n initialize();\n }\n }\n // ...\n}\n```\n\nThe 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.\n\n`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.\n\n`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.\n\n## The 2026 patch is the same one line in five files\n\nSaroj Khadka reported CAMEL-23313. Andrea Cosentino's commit `3d2efeed2`, dated April 13 2026, lands the fix:\n\n```\n$ git show 3d2efeed2 --stat\ncommit 3d2efeed2f6ea757f0254a1d1cdeb9a4f28ca147\nAuthor: Andrea Cosentino \nDate: Mon Apr 13 10:22:39 2026 +0200\n\n CAMEL-23313: HeaderFilter Strategies - add lowerCase where it's not present\n - JMS, SJMS, CoAP, Google PubSub (#22569)\n\n .../camel/coap/CoAPHeaderFilterStrategy.java | 1 +\n .../camel/component/google/pubsub/GooglePubsubHeaderFilterStrategy.java | 1 +\n .../camel/component/jms/ClassicJmsHeaderFilterStrategy.java | 1 +\n .../camel/component/jms/JmsHeaderFilterStrategy.java | 1 +\n .../camel/component/sjms/SjmsHeaderFilterStrategy.java | 1 +\n 5 files changed, 5 insertions(+)\n```\n\nThe diff for each of the five files is the same one line:\n\n```diff\n public JmsHeaderFilterStrategy(boolean includeAllJMSXProperties) {\n+ setLowerCase(true);\n setOutFilterStartsWith(DefaultHeaderFilterStrategy.CAMEL_FILTER_STARTS_WITH);\n setInFilterStartsWith(DefaultHeaderFilterStrategy.CAMEL_FILTER_STARTS_WITH);\n if (!includeAllJMSXProperties) {\n initialize();\n }\n }\n```\n\nThe five insertions, taken together, are byte-for-byte the same edit the original CVE-2025-27636 patch made to `HttpHeaderFilterStrategy` thirteen months earlier.\n\n## This is design-debt-driver. The five other vulnerable children were visible the day the substrate first produced the class.\n\nThis is a [design-debt-driver](/patterns/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.\"\n\nThe Tomcat `EncryptInterceptor` exhibit on the same pattern shows the recurring shape: [a security component generating consecutive CVEs from its primary security method](/posts/tomcat-encryptinterceptor-fails-open) 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.\n\nThe 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:\n\n> 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.\"\n\nThe 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.\n\nPoC: [akamai/CVE-2025-27636-Apache-Camel-PoC](https://github.com/akamai/CVE-2025-27636-Apache-Camel-PoC)","closing_line":"`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.","hook_md":"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.","post_id":55,"slug":"camel-cve-2026-40453-five-subclasses-needed-the-same-line","title":"CVE-2026-40453: Camel Patched One Header Filter In 2025. Five More Needed The Same Line.","type":"initial","unreadable_sentence":"The five insertions, taken together, are byte-for-byte the same edit the original CVE-2025-27636 patch made to HttpHeaderFilterStrategy thirteen months earlier."} -----BEGIN PGP SIGNATURE----- iHUEARYIAB0WIQRf0htP5+SjynlxywneZjl4jgkQJgUCahh3+wAKCRDeZjl4jgkQ JjZYAQDbdKveJqjIsBxxeJb4F5hAMobcyY1/Ng2LbZmd6BNyrwEAsffV+bH8TLTT Yxd8HXvULwrHkVPHYZOO1G822cHtIAA= =qVn6 -----END PGP SIGNATURE-----