Skip to content

CAMEL-24371: camel-a2a - fix WebhookUrlValidator address classification and host matching - #25406

Open
oscerd wants to merge 1 commit into
apache:mainfrom
oscerd:fix/CAMEL-24371
Open

CAMEL-24371: camel-a2a - fix WebhookUrlValidator address classification and host matching#25406
oscerd wants to merge 1 commit into
apache:mainfrom
oscerd:fix/CAMEL-24371

Conversation

@oscerd

@oscerd oscerd commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Description

WebhookUrlValidator classified webhook hosts in two places that did not agree with each other.

A host written as an IP literal was checked against a string prefix list (isPrivateIpv6), while a host reached through a name was classified with the InetAddress predicates. Those two do not cover the same ground — Inet6Address.isSiteLocalAddress() reports the deprecated fec0::/10 block and not the fc00::/7 unique local addresses that replaced it — so the same address was accepted or rejected depending on how it was written. Verified on JDK 21: fd00::1 and fc00::1 return false for all four predicates, while fec0::1 returns site=true.

The literal pre-check also prefix-matched the raw host string with startsWith("fc") / startsWith("fd") without first establishing that the host was an IP literal, so any name beginning with those two characters was rejected outright. https://fcm.googleapis.com/webhook and https://fd-edge.example.com/webhook were both refused.

Changes

Both paths now resolve the host and classify the resulting address with a single shared raw-byte classifier. InetAddress.getByName() already parses bracketed IPv6 literals without touching DNS, so the separate literal path is no longer needed and the two forms cannot drift apart again.

The classifier recognises these in addition to the loopback / wildcard / link-local / site-local ranges already handled:

Range Example
IPv6 unique local, fc00::/7 fd00::1
IPv4-compatible IPv6 ::10.0.0.1
NAT64 well-known prefix, 64:ff9b::/96 64:ff9b::a00:1
6to4, 2002::/16 2002:c0a8:101::1
Shared address space, 100.64.0.0/10 100.64.0.1

NAT64 and 6to4 addresses are classified by the IPv4 address they embed rather than blocked wholesale, so an IPv6-only deployment can still reach public webhook endpoints through a translation prefix.

IPv4-mapped IPv6 needs no new handling — the JDK returns an Inet4Address for ::ffff:x.x.x.x, so the existing IPv4 rules already applied.

Host names are no longer classified by their spelling.

Notes for reviewers

  • Exception message text changes. [fd00::1] now reports unique local instead of private/internal IPv6 ranges, and [::1] reports loopback instead of the IPv6 message. Four existing test assertions were updated accordingly. No API signature changed.
  • nonGlobalReason checks loopback even though a host reaching loopback directly is answered earlier (where allowLocal can let it through). That branch exists for the addresses embedding an IPv4 one — 64:ff9b::7f00:1 carries 127.0.0.1 — and is covered by a test.
  • A package-private HostResolver seam lets the resolved-host path be tested without DNS and without installing a JVM-wide InetAddressResolverProvider, which would have affected every test in the module.

Testing

WebhookUrlValidatorTest goes from 13 to 30 tests, covering each range above in both literal and resolved form, the adjacent addresses just outside 100.64.0.0/10, the NAT64/6to4 cases that must stay allowed, and the host names that were previously rejected for their spelling.

  • camel-a2a module suite: 519 tests, all passing
  • Full reactor build from root (mvn clean install -DskipTests): SUCCESS, no uncommitted regen artifacts

Documentation

Adds camel-4x-upgrade-guide-4_23.adoc with a note on the newly rejected ranges and the relaxed host-name matching, and registers it in the upgrade guide index.


Claude Code on behalf of @oscerd

…on and host matching

WebhookUrlValidator classified webhook hosts in two places that did not agree.
A host written as an IP literal was checked against a string prefix list, while a
host reached through a name was classified with the InetAddress predicates. Those
predicates do not cover the same ground: isSiteLocalAddress reports the deprecated
fec0::/10 block and not the fc00::/7 unique local addresses that replaced it, so
the same address was accepted or rejected depending on how it was written.

The literal pre-check also prefix-matched the raw host string without establishing
that the host was an IP literal, so any name beginning with fc or fd, such as
fcm.googleapis.com, was rejected outright.

Both paths now resolve the host and classify the resulting address with one shared
raw-byte classifier. InetAddress.getByName already parses bracketed IPv6 literals
without touching DNS, so the separate literal path is no longer needed. The
classifier additionally recognises fc00::/7, IPv4-compatible IPv6, the NAT64
well-known prefix 64:ff9b::/96, 6to4 under 2002::/16 and the shared address space
100.64.0.0/10. NAT64 and 6to4 addresses are classified by the IPv4 address they
embed, so a translation prefix carrying a globally routable address stays allowed.

A package-private resolver seam lets the resolved-host path be tested without DNS.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
@github-actions

github-actions Bot commented Aug 7, 2026

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

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • components/camel-ai/camel-a2a
  • docs

🔬 Scalpel shadow comparison — Scalpel: 10 tested, 28 compile-only — current: 9 all tested

Maveniverse Scalpel detected 38 affected modules (current approach: 9).

⚠️ Modules only in Scalpel (29)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-lucene
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-csimple-maven-plugin
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • docs
  • dummy-component

Skip-tests mode would test 10 modules (2 direct + 8 downstream), skip tests for 28 (generated code, meta-modules)

Modules Scalpel would test (10)
  • camel-a2a
  • camel-jbang-mcp
  • camel-jbang-plugin-mcp
  • camel-jbang-plugin-route-parser
  • camel-jbang-plugin-tui
  • camel-jbang-plugin-validate
  • camel-launcher-container
  • camel-yaml-dsl-validator
  • camel-yaml-dsl-validator-maven-plugin
  • docs
Modules with tests skipped (28)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-lucene
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-csimple-maven-plugin
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • dummy-component

ℹ️ Shadow mode — Scalpel observes but does not affect test execution. Learn more

All tested modules (38 modules)
  • Camel :: AI :: A2A
  • Camel :: All Components Sync point
  • Camel :: Assembly
  • Camel :: Catalog :: CSimple Maven Plugin (deprecated)
  • Camel :: Catalog :: Camel Catalog
  • Camel :: Catalog :: Camel Report Maven Plugin
  • Camel :: Catalog :: Camel Route Parser
  • Camel :: Catalog :: Console
  • Camel :: Catalog :: Dummy Component
  • Camel :: Catalog :: Lucene (deprecated)
  • Camel :: Catalog :: Maven
  • Camel :: Catalog :: Suggest
  • Camel :: Component DSL
  • Camel :: Coverage
  • Camel :: Docs
  • Camel :: Endpoint DSL
  • Camel :: Endpoint DSL :: Support
  • Camel :: Integration Tests
  • Camel :: JBang :: Core
  • Camel :: JBang :: Integration tests
  • Camel :: JBang :: MCP
  • Camel :: JBang :: Main
  • Camel :: JBang :: Plugin :: Edit
  • Camel :: JBang :: Plugin :: Generate
  • Camel :: JBang :: Plugin :: Kubernetes
  • Camel :: JBang :: Plugin :: MCP
  • Camel :: JBang :: Plugin :: Route Parser
  • Camel :: JBang :: Plugin :: TUI
  • Camel :: JBang :: Plugin :: Testing
  • Camel :: JBang :: Plugin :: Validate
  • Camel :: Kamelet Main
  • Camel :: Launcher
  • Camel :: Launcher :: Container
  • Camel :: YAML DSL
  • Camel :: YAML DSL :: Deserializers
  • Camel :: YAML DSL :: Maven Plugins
  • Camel :: YAML DSL :: Validator
  • Camel :: YAML DSL :: Validator Maven Plugin

⚙️ View full build and test results

@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.

The code changes to WebhookUrlValidator look solid — the single byte-based classifier is a clear improvement over the dual-path string+predicate approach, fixing real bugs where hostnames starting with "fc" or "fd" (like fcm.googleapis.com) were falsely rejected, and where fc00::/7 unique local addresses weren't caught by InetAddress.isSiteLocalAddress(). The HostResolver seam is clean for testing DNS-dependent code. Test coverage expansion from 13 to 30 tests is great, with proper AssertJ usage and conventions followed throughout.

One documentation concern: the upgrade guide entry is placed in a new camel-4x-upgrade-guide-4_23.adoc file, but main is currently at 4.22.0-SNAPSHOT (latest tag: camel-4.21.0). Changes merging to main now will ship with 4.22.0, so the behavioral changes should be appended to the existing camel-4x-upgrade-guide-4_22.adoc (which already has a camel-a2a section from CAMEL-23876). The new 4_23 file and its index entry in camel-4x-upgrade-guide.adoc are premature — users upgrading to 4.22 would miss this documentation.

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

Claude Code on behalf of @gnodet

@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.

Clean, well-tested security bug fix. The unified byte-based classifier is a clear improvement over the dual-path string+predicate approach, fixing real bugs (hostnames like fcm.googleapis.com falsely rejected, fc00::/7 not caught by isSiteLocalAddress()). Test expansion from 13 to 30 tests is thorough, covering each range in both literal and resolved form with proper boundary conditions. The HostResolver seam is a clean testability pattern.

Regarding the upgrade guide version: camel-4.22.0 was tagged today from the release branch, so the new camel-4x-upgrade-guide-4_23.adoc is the correct place for these behavioral changes — they will ship in 4.23.0, not 4.22.0.

This review covers project rules and conventions. It is not a replacement for specialized review tools such as CodeRabbit, Sourcery, or SonarCloud.

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

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