Skip to content

CAMEL-23769: camel-http-common - apply a configurable ObjectInputFilter when deserializing Java objects#24196

Open
oscerd wants to merge 1 commit into
mainfrom
fix/CAMEL-23769
Open

CAMEL-23769: camel-http-common - apply a configurable ObjectInputFilter when deserializing Java objects#24196
oscerd wants to merge 1 commit into
mainfrom
fix/CAMEL-23769

Conversation

@oscerd

@oscerd oscerd commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Fixes CAMEL-23769.

Problem

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 (defense-in-depth).

Change

  • HttpHelper — new overload deserializeJavaObjectFromStream(is, ctx, deserializationFilter) that calls ois.setObjectInputFilter(resolve(filter)) before readObject(); the existing 1-/2-arg methods delegate to it, so every call site is covered (the DefaultHttpBinding request side and the camel-http HttpProducer response side). resolveDeserializationFilter mirrors the siblings: configured pattern → JVM-wide jdk.serialFilter → conservative DEFAULT_DESERIALIZATION_FILTER.
  • HttpCommonComponent — new deserializationFilter @Metadata option (jdk.serialFilter syntax).
  • HttpBinding (SPI) — get/setDeserializationFilter added as default methods (no break for external HttpBinding implementations).
  • Wired in DefaultHttpBinding, HttpCommonEndpoint, JettyHttpEndpoint12, ServletEndpoint, and HttpProducer (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 denies java.net.**.
  • Full reactor build (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 fixVersions is at the maintainers' discretion.


Claude Code on behalf of Andrea Cosentino

…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>
@oscerd oscerd requested review from davsclaus and gnodet June 23, 2026 09:48

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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), matching JmsBinding.resolveDeserializationFilter() exactly.
  • Default filter matches camel-netty-http (includes JEP-290 graph-shape limits), appropriate since both read from network streams. The intentional difference from camel-jms (which omits maxdepth/maxrefs/maxbytes) is correct.
  • default methods on HttpBinding SPI preserve backward compatibility for external implementations.
  • Good test coverage with three targeted scenarios. Smart use of ArrayList instead of String (which bypasses TC_STRING class filtering).
  • Clear upgrade guide entry.

Minor suggestions (non-blocking):

  1. Filter caching: Unlike JmsBinding which resolves the filter once in the constructor (final field), HttpHelper.resolveDeserializationFilter() creates a new ObjectInputFilter on every deserialization call. Since this path is behind allowJavaSerializedObject=true (opt-in, rare), the overhead is negligible — but caching in DefaultHttpBinding would align with the JMS pattern.
  2. Shared constant follow-up: DEFAULT_DESERIALIZATION_FILTER and resolveDeserializationFilter() now exist in three places (HttpHelper, NettyConverter, JmsBinding). A shared utility in camel-support could reduce duplication.

This review was generated by an AI agent and may contain inaccuracies. Please verify all suggestions before applying.

@gnodet gnodet left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 {

/**

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-httpNettyHttpHelper.DEFAULT_DESERIALIZATION_FILTER = !java.net.**;java.**;javax.**;org.apache.camel.**;maxdepth=20;maxrefs=10000;maxbytes=10485760;!*
  • camel-vertx-httpVertxHttpHelper — identical, with the limits
  • camel-nettyNettyConverter — identical, with the limits
  • camel-jmsJmsBinding is 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

@oscerd

oscerd commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review and approval, @davsclaus. On the two non-blocking suggestions:

  1. Filter cachingHttpHelper.resolveDeserializationFilter is a stateless static helper shared by both the consumer (DefaultHttpBinding) and the producer (HttpProducer), so unlike JmsBinding there's no single binding instance to cache a final field on. ObjectInputFilter.Config.createFilter(...) only runs on the opt-in allowJavaSerializedObject / transferException path (rare), so as you noted the overhead is negligible — I've kept the helper stateless rather than thread a cached ObjectInputFilter through the API. Glad to revisit it together with the shared-utility refactor below.

  2. Shared utility — agreed: DEFAULT_DESERIALIZATION_FILTER + resolveDeserializationFilter() now live in HttpHelper, NettyHttpHelper / NettyConverter, VertxHttpHelper and JmsBinding, and consolidating them into camel-support would reduce the duplication (and would be the right place to also unify the camel-jms default per @gnodet's comment). I'd prefer to do that as a separate follow-up rather than widen this PR's scope.

Claude Code on behalf of Andrea Cosentino

@oscerd

oscerd commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

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

@github-actions

Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • catalog/camel-catalog
  • components/camel-atmosphere-websocket
  • components/camel-http-common
  • components/camel-http
  • components/camel-jetty
  • components/camel-servlet
  • docs
  • dsl/camel-componentdsl

ℹ️ Dependent modules were not tested because the total number of affected modules exceeded the threshold (50). Use the test-dependents label to force testing all dependents.

⚠️ Some tests are disabled on GitHub Actions (@DisabledIfSystemProperty(named = "ci.env.name")) and require manual verification:

  • components/camel-jetty: 1 test(s) disabled on GitHub Actions
Build reactor — dependencies compiled but only changed modules were tested (8 modules)
  • Camel :: Atmosphere WebSocket Servlet
  • Camel :: Catalog :: Camel Catalog
  • Camel :: Component DSL
  • Camel :: Docs
  • Camel :: HTTP
  • Camel :: HTTP :: Common
  • Camel :: Jetty
  • Camel :: Servlet

⚙️ View full build and test results

@oscerd oscerd requested a review from gnodet June 23, 2026 12:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants