Skip to content

CAMEL-23609: Tighten in-code ObjectInputFilter defaults with JEP-290 graph-shape limits#23523

Merged
oscerd merged 1 commit into
apache:mainfrom
oscerd:fix/CAMEL-23609
May 27, 2026
Merged

CAMEL-23609: Tighten in-code ObjectInputFilter defaults with JEP-290 graph-shape limits#23523
oscerd merged 1 commit into
apache:mainfrom
oscerd:fix/CAMEL-23609

Conversation

@oscerd
Copy link
Copy Markdown
Contributor

@oscerd oscerd commented May 26, 2026

Summary

Follow-up to the CAMEL-23297 / CAMEL-23319 / CAMEL-23321 / CAMEL-23322 / CAMEL-23324 / CAMEL-23372 series. The in-code default ObjectInputFilter shipped by the components below now also carries JEP-290 graph-shape limits (maxdepth=20, maxrefs=10000, maxbytes=10485760) in addition to the existing class allowlist. The class allowlist is unchanged.

Affected sites (9):

Component File
camel-infinispan DefaultExchangeHolderUtils.java
camel-mina MinaConverter.java
camel-netty NettyConverter.java
camel-netty-http NettyHttpHelper.java
camel-vertx-http VertxHttpHelper.java
camel-leveldb LevelDBAggregationRepository.deserializationFilter
camel-cassandraql CassandraAggregationRepository.deserializationFilter
camel-consul ConsulRegistry.deserializationFilter
camel-sql JdbcAggregationRepository.deserializationFilter

For the 4 configurable defaults a package-private DEFAULT_DESERIALIZATION_FILTER constant is introduced so the value lives in one place and is referenced both by the field initializer and the @Metadata(defaultValue = ...) attribute. This keeps the catalog metadata JSONs, the javadoc and the field default in sync.

Why graph-shape clauses and not just the class allowlist?

The current class allowlist (!java.net.**;java.**;javax.**;org.apache.camel.**;!*) blocks gadget-chain RCE but does not bound how deep, how wide or how large an inbound serialized graph can be. Adding maxdepth / maxrefs / maxbytes is the standard JEP-290 way to bound CPU/memory cost during readObject() and is a pure defense-in-depth improvement.

Operator overrides preserved

  • JVM-wide -Djdk.serialFilter still takes precedence over the Camel default in every site that ships one.
  • The configurable repositories and endpoint configurations (LevelDBAggregationRepository, JdbcAggregationRepository, CassandraAggregationRepository, ConsulRegistry, netty-http / vertx-http endpoint configuration) already expose a deserializationFilter @UriParam accepting a fully custom filter string, including structural clauses or none at all.

Intentionally not changed: camel-jms / camel-sjms

Both apply their filter as a post-deserialization class check (after the JMS provider has already decoded the payload via its own ObjectInputStream). Graph-shape limits are therefore no-ops in those sites and have not been added. DoS hardening on the JMS path must be configured at the JMS provider level (Artemis deserializationAllowList, ActiveMQ Classic SERIALIZABLE_PACKAGES) or via -Djdk.serialFilter. The upgrade-guide entry calls this out explicitly.

Tests

A small DefaultFilterTest (or equivalent test method added to an existing class) at each of the 9 sites asserts that the resolved default filter contains maxdepth=, maxrefs= and maxbytes=. For the 4 configurable sites the test additionally constructs the repository and asserts getDeserializationFilter() returns the same DEFAULT_DESERIALIZATION_FILTER constant.

Upgrade guide

docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc gains a "Tightened default ObjectInputFilter across deserialization sites - potential breaking change" entry listing the affected components, the new defaults and the override paths, and noting the JMS exclusion.

Test plan

  • Module-level mvn -B -DskipITs test on each of the 9 changed modules - all pass locally. (One unrelated NettyTCPSyncUDSTest failure on local FS with long UDS path; not related to this change.)
  • Full reactor mvn -B clean install -DskipTests succeeds; downstream catalog mirrors in catalog/camel-catalog/.../beans/ regenerated and committed.
  • CI green.

Notes for reviewers

The new structural defaults are conservative (maxdepth=20, maxrefs=10000, maxbytes=10MB). They are intended to comfortably handle a DefaultExchangeHolder carrying a typical Exchange payload but to reject extremely deep / very wide / multi-megabyte graphs. If a route legitimately needs to deserialize a graph that exceeds any of these, the per-endpoint deserializationFilter option or -Djdk.serialFilter is the existing escape hatch.


Claude Code on behalf of Andrea Cosentino

…graph-shape limits

Adds maxdepth=20;maxrefs=10000;maxbytes=10485760 to the in-code default
ObjectInputFilter used by the components that perform Java deserialization
through a real ObjectInputStream:

  - camel-infinispan (DefaultExchangeHolderUtils)
  - camel-mina (MinaConverter)
  - camel-netty (NettyConverter)
  - camel-netty-http (NettyHttpHelper)
  - camel-vertx-http (VertxHttpHelper)
  - camel-leveldb (LevelDBAggregationRepository.deserializationFilter)
  - camel-cassandraql (CassandraAggregationRepository.deserializationFilter)
  - camel-consul (ConsulRegistry.deserializationFilter)
  - camel-sql (JdbcAggregationRepository.deserializationFilter)

The class allowlist is unchanged; only structural JEP-290 clauses are added.
Operators retain their existing overrides:

  - JVM-wide -Djdk.serialFilter takes precedence over the Camel default.
  - The configurable repositories and endpoint configurations expose a
    deserializationFilter @UriParam that accepts a fully custom filter
    string, including the structural clauses.

For the 4 configurable defaults a package-private DEFAULT_DESERIALIZATION_FILTER
constant is introduced so the value lives in one place and is referenced both
by the field initializer and by the @metadata defaultValue attribute, keeping
the catalog metadata, javadoc and field default in sync.

camel-jms and camel-sjms are intentionally NOT updated: they apply the filter
as a post-deserialization class check (after the JMS provider has already
decoded the payload), so JEP-290 graph-shape clauses are no-ops in those
sites. DoS hardening on the JMS path must be configured at the JMS provider
level (Artemis deserializationAllowList, ActiveMQ Classic SERIALIZABLE_PACKAGES)
or via -Djdk.serialFilter.

Adds a test at each affected site asserting the structural clauses are
present in the resolved default filter, and adds an upgrade-guide entry on
main for 4.21 with the override paths.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
@oscerd oscerd requested review from davsclaus, gzurowski and orpiske May 26, 2026 09:34
@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.

Copy link
Copy Markdown
Contributor

@gnodet gnodet left a comment

Choose a reason for hiding this comment

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

Excellent security hardening. Adding JEP-290 graph-shape limits (maxdepth=20;maxrefs=10000;maxbytes=10485760) to the default ObjectInputFilter across all 9 deserialization sites is a solid defense-in-depth measure against deserialization attacks that exploit deeply nested or excessively large object graphs.

The limits are applied consistently across camel-infinispan, camel-mina, camel-netty, camel-netty-http, camel-vertx-http, camel-leveldb, camel-cassandraql, camel-consul, and camel-sql. The upgrade guide is thorough, documenting override paths for users who need different limits.

This follows the pattern of prior CVE fixes (CVE-2024-22369 et al.) that hardened these same sites, now adding the complementary graph-shape constraints.

LGTM.

Fully automatic review from Claude Code

@oscerd oscerd merged commit ab4e81c into apache:main May 27, 2026
7 checks passed
@oscerd oscerd deleted the fix/CAMEL-23609 branch May 27, 2026 07:21
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