CAMEL-23769: camel-http-common - apply a configurable ObjectInputFilter when deserializing Java objects#24196
CAMEL-23769: camel-http-common - apply a configurable ObjectInputFilter when deserializing Java objects#24196oscerd wants to merge 1 commit into
Conversation
davsclaus
left a comment
There was a problem hiding this comment.
Good security hardening PR — adds ObjectInputFilter defense-in-depth to camel-http-common's Java deserialization path, aligning it with camel-netty-http and camel-jms.
Strengths:
- Correct 3-step resolution logic (configured pattern → JVM-wide
jdk.serialFilter→ default Camel filter), matchingJmsBinding.resolveDeserializationFilter()exactly. - Default filter matches
camel-netty-http(includes JEP-290 graph-shape limits), appropriate since both read from network streams. The intentional difference fromcamel-jms(which omitsmaxdepth/maxrefs/maxbytes) is correct. defaultmethods onHttpBindingSPI preserve backward compatibility for external implementations.- Good test coverage with three targeted scenarios. Smart use of
ArrayListinstead ofString(which bypassesTC_STRINGclass filtering). - Clear upgrade guide entry.
Minor suggestions (non-blocking):
- Filter caching: Unlike
JmsBindingwhich resolves the filter once in the constructor (finalfield),HttpHelper.resolveDeserializationFilter()creates a newObjectInputFilteron every deserialization call. Since this path is behindallowJavaSerializedObject=true(opt-in, rare), the overhead is negligible — but caching inDefaultHttpBindingwould align with the JMS pattern. - Shared constant follow-up:
DEFAULT_DESERIALIZATION_FILTERandresolveDeserializationFilter()now exist in three places (HttpHelper,NettyConverter,JmsBinding). A shared utility incamel-supportcould reduce duplication.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
gnodet
left a comment
There was a problem hiding this comment.
Nice work on this security-hardening PR — the implementation follows established patterns from the sibling components well, the SPI change is backward-compatible via default methods, all call sites are covered, and the documentation/tests are adequate.
One item worth discussing: the default filter pattern includes JEP-290 graph-shape limits (maxdepth=20;maxrefs=10000;maxbytes=10485760) that are not present in any of the sibling components (camel-netty-http, camel-jms, camel-vertx-http), which all use:
!java.net.**;java.**;javax.**;org.apache.camel.**;!*
This is arguably a stronger defense, but it creates an inconsistency: a payload that deserializes successfully via camel-netty-http could fail via camel-http if it exceeds these limits. The PR description claims to "align" with siblings, so this should be a deliberate choice rather than an accidental divergence. Options:
- Remove the limits to truly align, or
- Keep them and update the siblings in a follow-up to unify the default, or
- Explicitly acknowledge this as an intentional improvement
Overall this looks good — well-structured, backward-compatible, and well-tested.
This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.
Claude Code on behalf of Guillaume Nodet
|
|
||
| public final class HttpHelper { | ||
|
|
||
| /** |
There was a problem hiding this comment.
This default filter includes maxdepth=20;maxrefs=10000;maxbytes=10485760 which none of the sibling components (camel-netty-http, camel-vertx-http, camel-jms) include in their DEFAULT_DESERIALIZATION_FILTER. Their default is:
!java.net.**;java.**;javax.**;org.apache.camel.**;!*
Is this intentional? If so, it would be good to unify across all components in a follow-up. If not, dropping the graph-shape limits here would align exactly with the siblings.
Claude Code on behalf of Guillaume Nodet
There was a problem hiding this comment.
Thanks for the careful look. I double-checked the sibling defaults, and the JEP-290 graph-shape limits are in fact present in the two HTTP siblings — so this is deliberately aligned rather than divergent:
- camel-netty-http —
NettyHttpHelper.DEFAULT_DESERIALIZATION_FILTER=!java.net.**;java.**;javax.**;org.apache.camel.**;maxdepth=20;maxrefs=10000;maxbytes=10485760;!* - camel-vertx-http —
VertxHttpHelper— identical, with the limits - camel-netty —
NettyConverter— identical, with the limits - camel-jms —
JmsBindingis the only one that omits them (…org.apache.camel.**;!*)
So camel-http-common now matches the HTTP-stream siblings (netty-http / vertx-http) exactly; the only difference is from camel-jms, which reads from a broker rather than a raw network socket where the graph-shape limits matter most. The inclusion here is intentional and consistent with the components that, like this one, deserialize from network streams. Happy to unify the camel-jms default into the same pattern in a follow-up if we'd prefer a single shared default everywhere.
Claude Code on behalf of Andrea Cosentino
|
Thanks for the review and approval, @davsclaus. On the two non-blocking suggestions:
Claude Code on behalf of Andrea Cosentino |
|
Follow-up for the shared-utility consolidation (and unifying the camel-jms default) tracked as CAMEL-23815 (targeting 4.22.0). Claude Code on behalf of Andrea Cosentino |
|
🌟 Thank you for your contribution to the Apache Camel project! 🌟 🐫 Apache Camel Committers, please review the following items:
|
|
🧪 CI tested the following changed modules:
Build reactor — dependencies compiled but only changed modules were tested (8 modules)
|
|
@oscerd conflict on upgrade guide to resolve |
…er when deserializing Java objects HttpHelper.deserializeJavaObjectFromStream read a Java-serialized object via CamelObjectInputStream without an ObjectInputFilter. This is only reachable behind the opt-in allowJavaSerializedObject / transferException options, but the sibling camel-netty-http, camel-jms and camel-vertx-http bindings already apply a filter on that path. This aligns camel-http-common with them: a new overload applies an ObjectInputFilter (setObjectInputFilter) before readObject, and the existing methods delegate to it so all call sites (DefaultHttpBinding request side and the camel-http HttpProducer response side) are covered. A new deserializationFilter component option (jdk.serialFilter syntax) on HttpCommonComponent lets it be customised; when unset, the JVM-wide jdk.serialFilter is used if present, otherwise a conservative default filter (denying java.net.**, allowing java.**/javax.**/org.apache.camel.**, with JEP-290 graph-shape limits) is applied. The option is plumbed through the HttpBinding SPI (as default methods for backward compatibility) and wired in HttpCommonEndpoint, JettyHttpEndpoint12 and ServletEndpoint. Adds HttpHelperDeserializationTest and a 4.21 upgrade-guide note. Regenerates the component metadata for http, jetty, servlet and atmosphere-websocket. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
Fixes CAMEL-23769.
Problem
HttpHelper.deserializeJavaObjectFromStreamread a Java-serialized object viaCamelObjectInputStreamwithout anObjectInputFilter. This is only reachable behind the opt-inallowJavaSerializedObject/transferExceptionoptions, but the siblingcamel-netty-http,camel-jmsandcamel-vertx-httpbindings already apply a filter on that path. This alignscamel-http-commonwith them (defense-in-depth).Change
HttpHelper— new overloaddeserializeJavaObjectFromStream(is, ctx, deserializationFilter)that callsois.setObjectInputFilter(resolve(filter))beforereadObject(); the existing 1-/2-arg methods delegate to it, so every call site is covered (theDefaultHttpBindingrequest side and the camel-httpHttpProducerresponse side).resolveDeserializationFiltermirrors the siblings: configured pattern → JVM-widejdk.serialFilter→ conservativeDEFAULT_DESERIALIZATION_FILTER.HttpCommonComponent— newdeserializationFilter@Metadataoption (jdk.serialFiltersyntax).HttpBinding(SPI) —get/setDeserializationFilteradded asdefaultmethods (no break for externalHttpBindingimplementations).DefaultHttpBinding,HttpCommonEndpoint,JettyHttpEndpoint12,ServletEndpoint, andHttpProducer(camel-http).Default filter:
!java.net.**;java.**;javax.**;org.apache.camel.**;maxdepth=20;maxrefs=10000;maxbytes=10485760;!*.Tests
HttpHelperDeserializationTest— configured filter rejects a denied class, allows a permitted one, and the default filter deniesjava.net.**.mvn clean install -DskipTests, 2365 modules) green; metadata regenerated for http/jetty/servlet/atmosphere-websocket (the new option + index shift only, verified no unrelated drift).Documentation
camel-4x-upgrade-guide-4_21.adoc— note for the HTTP components.Compatibility / backport
Behaviour change: on the opt-in deserialization path, a payload referencing a denied class may now be rejected. This is a new option (config surface), so per project convention it likely targets 4.21.0; final
fixVersionsis at the maintainers' discretion.Claude Code on behalf of Andrea Cosentino