Skip to content

CAMEL-25644: camel-ssh - match known_hosts entries by exact host pattern - #27821

Merged
oscerd merged 10 commits into
apache:mainfrom
oscerd:fix/CAMEL-25644
Oct 19, 2026
Merged

oscerd merged 10 commits into
apache:mainfrom
oscerd:fix/CAMEL-25644

Conversation

@oscerd

@oscerd oscerd commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

CAMEL-25644

When knownHostsResource is set, ResourceBasedSSHKeyVerifier parsed the known_hosts resource with its own parser:

  • it compared the host field with String.contains and used only the first matching line;
  • it did not tell [host]:port entries from plain ones;
  • it skipped every line that was not exactly host type key (comments, markers, extra whitespace, CRLF);
  • it had no support for wildcard, negated or hashed patterns;
  • it looked up an endpoint configured with an address by the name that a reverse lookup of that address returns.

Changes

  • Matching. The verifier reads each line and matches the entries as OpenSSH does (hostfile.c, match_hostname):
    • Each host pattern is compared, ignoring case, with the name OpenSSH looks the server up by: the host name or address the client connects to (the host configured on the endpoint, or the HostName that ~/.ssh/config gives for it), never resolved through DNS, written host for port 22 and [host]:port for another port.
    • The producer and the consumer resolve the host configuration once per connection, with the resolver of the client (~/.ssh/config by default, or the resolver of a custom clientBuilder), as SshClient.connect(username, host, port) does. They connect with that entry and put it in the connection context (ResourceBasedSSHKeyVerifier.HOST_CONFIG_ENTRY).
    • The verifier reads that entry from the session and uses its HostName as written. It never resolves again. A host reached through a jump host uses SSHD's TARGET_SERVER; the jump host itself uses its own address.
    • So an IPv6 address such as ::1, configured on the endpoint or given as HostName, is not expanded to 0:0:0:0:0:0:0:1. A host configuration that cannot resolve the host fails the connection before any server is contacted.
    • Without that entry, for example with the verifier used outside the producer and consumer, the connected address is used.
    • * and ? are wildcards, ! excludes the hosts a pattern matches, and hashed |1|salt|hash entries (20-byte salt and digest) are supported.
    • So ![excluded.example.com]:2222,[db.example.com]:2222 works, and * applies to every host and port.
  • Keys. Every entry for the host is considered. The keys are resolved and compared with Apache MINA SSHD (PublicKeyEntry, KeyUtils.compareKeys), the same code that decodes the key the server presents.
  • Which keys are rejected:
    • a key listed in a matching @revoked entry, whatever the value of failOnUnknownHost;
    • any key when the host has entries without a marker but none of them lists that key, whatever the value of failOnUnknownHost.
  • What lists a host. failOnUnknownHost only decides for a host without an entry without a marker. As in OpenSSH (hostfile.c, check_hostkeys_by_key_or_type), @revoked and @cert-authority entries do not list a host. @cert-authority entries are ignored: host certificates are not supported, as before.
  • Fail closed. A resource that cannot be read, or a line that cannot be read, makes every connection fail, so a parse failure can never turn a listed host into an unknown one. A line cannot be read when it has an unknown @ marker, a missing key, a key that is not valid base64, or a hashed host that is not a |1| entry with a 20-byte salt and digest. A key of a type that SSHD does not support only lists the host.
  • Removed. The verifier's own key decoding (loadKey) is removed. SSHPublicKeyHolder is no longer used by the verifier; it is kept because it is a public class.
  • Docs. The descriptions of knownHostsResource and failOnUnknownHost now state these rules, and ssh-component.adoc has a new "Server host key verification" section.

Behaviour changes

The upgrade-guide note is added on main in three places: the 4.24 guide, the new "Upgrading from 4.22.2 to 4.22.3" section (4.22.2 has been cut), and the "Upgrading from 4.18.5 to 4.18.6" section. The fix is to be backported to camel-4.22.x and camel-4.18.x. The note covers these changes:

  • a pattern such as db.example.com only applies to port 22;
  • an endpoint configured with a host name no longer uses entries listed only under its address, and an endpoint configured with an address no longer uses entries listed under its reverse-lookup name;
  • an entry for another host whose name or address contains the configured one is no longer used;
  • a resource or line that cannot be read now fails every connection.

Tests

  • ResourceBasedSSHKeyVerifierTest, 22 tests, covers:
    • exact host patterns and addresses, and ports;
    • patterns against [host]:port, including * on another port;
    • negated port-qualified patterns;
    • wildcard, upper-case and hashed patterns, the hashed ones on both ports;
    • several keys per host, comments and CRLF line endings;
    • a revoked key on ports 22 and 2222 with both values of failOnUnknownHost, with the revocation before and after the accepted entry;
    • a host with only @revoked entries;
    • unreadable lines, alone and after a valid entry, including malformed hashed hosts and the |2| prefix, and an unreadable resource;
    • @cert-authority entries, and unknown versus listed hosts with both values of failOnUnknownHost;
    • an endpoint configured with an address, and the host configuration of the connection (::1, [::1], a host name, or none);
    • a target reached through a jump host, and the jump host itself;
    • every key type of known_hosts_types (RSA, DSA, ECDSA 256/384/521, Ed25519).
  • How the tests were checked:
    • On the code before this PR, 11 of the first 14 verifier tests fail.
    • On this PR's first commit (aa8050b), the 5 tests added in the first review round fail.
    • A mutation that accepts a listed key before reading the later lines fails 2 tests.
  • SshComponentKnownHostTest and SshComponentKnownHostEdDSATest:
    • The test server listens on a random port, so the known_hosts files are written at runtime, with [localhost]:<port> entries for the server's own host key. The known_hosts_valid and known_hosts_eddsa fixtures are removed.
    • Two end-to-end tests fail on the previous verifier: a key listed only for another host is rejected, and a server listed with several keys is accepted.
  • SshComponentKnownHostIPv6Test connects over ::1 with the listed key and another key, under both values of failOnUnknownHost. It does this with the endpoint configured as ::1, and with an alias that the client's host configuration resolves to HostName ::1. For the alias, the host configuration answers only once. It skips itself where the IPv6 loopback address is not available. On ef7e70d36ac7, which looked the host up a second time, the alias cases fail.
  • SshComponentKnownHostTest adds a hostname alias (db-alias → HostName localhost), and a host configuration that cannot resolve the host, under both values of failOnUnknownHost. Every connection test asserts whether the test server received credentials, a password or a public key. Rejected peers and unresolved hosts receive none.
  • camel-ssh: 74 tests, 0 failures.
  • Full reactor mvn clean install -DskipTests -DskipITs: BUILD SUCCESS, 706 modules (last run on 21d7485, after merging current main). The regenerated catalog (component JSON and doc mirror) and the component and endpoint DSL builders are included.

Claude Code on behalf of Andrea Cosentino (@oscerd)

🤖 Generated with Claude Code

ResourceBasedSSHKeyVerifier parsed the known_hosts resource with its own
parser: it compared the host field with String.contains, used only the
first matching line, did not tell [host]:port entries from plain ones,
skipped comments, markers and hashed entries, and looked up an endpoint
configured with an address by the name of a reverse lookup.

Read and match the entries with Apache MINA SSHD's KnownHostEntry against
the host and port configured on the endpoint, consider every entry of the
host, reject a key listed in a matching @Revoked entry, and keep rejecting
a host that has entries but presents a key none of them lists, whatever
failOnUnknownHost is set to. Document the supported format and add the
upgrade-guide notes for 4.24, 4.22.2 and 4.18.6.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
@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.

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

Solid improvement overall — the delegation to MINA SSHD's own parser eliminates a class of bugs cleanly. One correctness issue in the revoked-entry handling.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

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

Requesting changes for the host-key validation issues below, verified against aa8050b.

The existing camel-ssh suite passes: 54 tests, zero failures/errors. Additional verifier probes and real loopback SSH connections exposed a regression that accepts an unlisted key and incomplete wildcard revocation enforcement. Both connection probes reached password authentication with synthetic credentials. The negated-pattern regression was also checked against the preceding implementation, which rejected the same connection.

Please address the inline findings and add regression coverage. The revocation tests should cover nondefault ports and both entry orders: an experimental mutation that returns immediately on an allowed key, before considering later revocations, still passes all 14 verifier tests.

CI at submission: Java 17/25 builds, documentation validation, and license checks are queued; dependency review passed; Sonar is skipped. I ran the component suite, not the full reactor.

AI-generated review by Codex on behalf of @luigidemasi.

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

Thanks @oscerd. Replacing the String.contains lookup and the hand-written key decoder with Apache MINA SSHD's KnownHostEntry and KeyUtils.compareKeys is the right direction. The new tests cover exact names, addresses, ports, hashed entries and several keys per host. The upgrade-guide entry is on main in the 4.24 guide and in the 4.22.2 and 4.18.6 sections, which matches the backport policy. I read the SSHD 2.20.0 sources (KnownHostEntry, HostPatternsHolder, KnownHostHashValue, KnownHostsServerKeyVerifier, AbstractClientSession.checkKeys) to check the open threads. CI is still running.

The open threads

  • @luigidemasi, ![excluded.example.com]:2222,[db.example.com]:2222: I agree. HostPatternsHolder.toPattern only reads the [host]:port form when [ is the first character. For ![...] it then rejects [ as an invalid pattern character. readKnownHostEntries catches that, logs a WARN and drops the whole line, so a listed host becomes an unknown host. One way to keep this safe: parse line by line with KnownHostEntry.parseKnownHostEntry, and when a line cannot be parsed, do not fall through to the failOnUnknownHost=false acceptance for that verification. Another way is to rewrite a leading ![ before handing the pattern to SSHD.
  • @luigidemasi, @revoked * and non-default ports: I agree. A pattern without a port gets port 0, and isPortMatch maps 0 to 22, so * never matches port 2222. OpenSSH matches patterns against the string [host]:port for a non-default port, so * matches there. See also my inline comment on the docs, because the same gap affects plain wildcard entries.
  • @luigidemasi, unknown markers: I agree. parseKnownHostEntry keeps any marker text. OpenSSH accepts only @revoked and @cert-authority and skips a line with any other marker. Treating only marker == null as a trusted entry fixes it. SSHD's own KnownHostsServerKeyVerifier has the same gap, so this is not something the library already solves.
  • gnodet-bot, a host with only @revoked entries: I disagree that this is a bug in the code. OpenSSH does not count @revoked lines when it decides whether a host is known; it only checks them for revocation. SSHD's KnownHostsServerKeyVerifier.acceptKnownHostEntries does the same: with no non-revoked match it calls acceptUnknownHostKey. The current code follows both. The docs and the PR description say "a host that has entries", which includes @revoked lines, so the wording should change rather than the code (inline comment). The stricter behaviour is also defensible, but then the docs should say that it differs from OpenSSH.
  • gnodet-bot, <p/>: this is common Camel javadoc style (several hundred files in camel-api use it), so I would leave it.

Can Camel reuse the library instead of its own parser? It already does. This PR reads the entries with SSHD's parser and only keeps the decision logic (about 40 lines) in Camel. The other option is to extend SSHD's KnownHostsServerKeyVerifier, as MinaSftpServerKeyVerifier in camel-mina-sftp does, and override reloadKnownHosts to read the Camel resource. That would make the two components behave the same. But it is built around a Path: when an unknown host is accepted, acceptUnknownHostKey writes the new entry back to that file. It also uses the same isHostMatch, so it has the same gaps with port wildcards, ![...] patterns and unknown markers. So the approach in this PR is fine. The three gaps above need a few lines in Camel, and could also be reported to SSHD, because camel-mina-sftp has them too.

Smaller points

  • SSHPublicKeyHolder is no longer used anywhere in Camel. Keeping it is right, but consider marking it @Deprecated, so it can be removed later.
  • Please add tests for the three cases above: @revoked * on ports 22 and 2222 in both entry orders, a ![...]:port entry, and an @unknown marker, each with both values of failOnUnknownHost. The module uses JUnit assertions, so the new tests in ResourceBasedSSHKeyVerifierTest follow the module's style.

Checked against the project conventions in CLAUDE.md. This is a rules-and-conventions review and does not replace CodeRabbit, Sourcery or SonarCloud.

Claude Code on behalf of @davsclaus.

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

Comment thread components/camel-ssh/src/main/docs/ssh-component.adoc Outdated
Comment thread components/camel-ssh/src/main/docs/ssh-component.adoc Outdated
Read the known_hosts lines in the verifier instead of with MINA SSHD's
KnownHostEntry, whose pattern parser drops a line with a negated
port-qualified pattern such as ![host]:2222 and only applies a pattern
without a port, * included, to port 22. Each host pattern, and each
hashed entry, is now matched against the name OpenSSH looks the server
up by: host for port 22 and [host]:port for another port.

A resource or a line that cannot be read, including one with a marker
other than @Revoked or @cert-authority, now makes every connection fail,
so a parse failure can no longer turn a listed host into an unknown one.
Keys are still resolved and compared with MINA SSHD.

Say in the docs, the option descriptions and the upgrade notes that only
entries without a marker list a host, as in OpenSSH.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>

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

Thanks @oscerd. I re-read ResourceBasedSSHKeyVerifier at 3700546. SSHD's HostPatternsHolder has the gaps found in the last round, so reading the lines in Camel and matching each pattern against host / [host]:port is a reasonable trade. The parser stays small.

What I checked:

  • The three findings from @luigidemasi are fixed in the code. ![excluded.example.com]:2222,[db.example.com]:2222 is read per pattern, with ! handled before the match. * is matched against [db.example.com]:2222, so @revoked * applies on port 2222. Only @revoked and @cert-authority are accepted as markers; any other marker makes the line unreadable. The tests cover both values of failOnUnknownHost, both entry orders, and ports 22 and 2222.
  • A host with only @revoked entries stays unknown, as in OpenSSH. The docs, the failOnUnknownHost description and javadoc, and the upgrade notes now say "entries without a marker". The 4.18, 4.22 and 4.24 notes have the same text, and the generated metadata and the catalog copy of ssh-component.adoc are in sync.
  • The name to match comes from SshdSocketAddress.toSshdSocketAddress, which uses getHostString(), so there is no reverse lookup. Hashed entries hash the same lower-cased host / [host]:port string that OpenSSH hashes.
  • matchesPattern is a plain backtracking glob for * and ?. A negated pattern excludes the entry, and an empty pattern is skipped.
  • The class javadoc now uses <p>, and the verifier only accepts after it has read every line.

Notes, not blocking:

  • An unreadable line, or a resource that cannot be read, now rejects every connection whatever failOnUnknownHost is set to. That is stricter than OpenSSH, which skips a line it cannot parse. It also turns a missing resource from "accepted, with a DEBUG log" into "every connection fails" in the 4.18.x and 4.22.x patch releases. It is the safer choice, and the docs and upgrade notes say so, so I am fine with it. The WARN names the line number, which will help users find the line.
  • SSHPublicKeyHolder is still unused and not marked @Deprecated. Optional.

@luigidemasi, your three findings look fixed to me at this commit. Please have a look when you can.

CI is still running.

Checked against the project conventions in CLAUDE.md. This is a rules-and-conventions review and does not replace CodeRabbit, Sourcery or SonarCloud.

Claude Code on behalf of @davsclaus.

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

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

Re-review after commit 3700546.

Clean rewrite. All prior findings are addressed. The custom known_hosts parser correctly implements OpenSSH matching semantics with proper negation handling, hashed entry support, revocation logic, and port-qualified patterns. No real issues found.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@gnodet gnodet added the lts label Oct 14, 2026

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

Re-reviewed 3700546. The three findings from my previous review are fixed: negated port-qualified patterns retain their key constraints, wildcard revocation applies on nondefault ports in both entry orders, and unsupported markers reject the connection.

Verification:

  • All 60 camel-ssh tests pass.
  • All original verifier probes now pass.
  • The original loopback SSH probes now reject the unlisted/revoked keys before password authentication; the test servers receive no synthetic password.
  • Five tests in the updated verifier suite fail against the initial PR implementation.
  • The previously surviving early-accept mutation now fails two tests.
  • 100,000 comparisons of the new glob matcher against an independent dynamic-programming implementation pass.

I am still requesting changes for the two findings below. The malformed-hash finding is a gap in the replacement parser's new fail-closed contract. The IPv6 finding is pre-existing: I reproduced it against the code before this PR as well, so it must not be described as a regression introduced here. It remains directly relevant to the configured-host lookup and key-pinning guarantees being documented by this change.

CI at submission: Java 17/25 builds, documentation validation, and licensing checks remain queued; dependency review passed; Sonar is skipped. I ran the component suite, not the full reactor.

AI-generated review by Codex on behalf of @luigidemasi.

…hashed entries

The verifier took the host from the address the client connected to,
whose host string writes an IPv6 address such as ::1 as
0:0:0:0:0:0:0:1, so an entry for [::1]:port was never found. The
producer and the consumer now pass the host configured on the endpoint
to the verifier, which uses it as written (without the brackets of an
IPv6 address) with the port the client connected to. The existing
constructors still use the connected address.

A host field that starts with | must be a |1|salt|hash entry whose salt
and hash both decode to 20 bytes; anything else makes the line
unreadable, which makes every connection fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
@github-actions github-actions Bot removed the lts label Oct 14, 2026

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

Re-reviewed a1d570a. All findings from my previous reviews are addressed, and I found no further critical or major issues.

Both the producer and consumer now preserve the configured host for known_hosts lookup, including compressed IPv6 addresses. Malformed hashed entries, including unsupported prefixes and invalid salt/digest lengths, fail closed. The earlier negated-pattern, revocation and marker fixes remain effective.

Validation: the complete camel-ssh component suite passed (65 tests, zero failures/errors/skips, including all four IPv6 connection tests). Independent loopback SSH probes confirmed that matching IPv6 keys authenticate and rejected peers receive no test password. Additional verifier probes passed, and targeted mutations confirmed that regression tests detect lost host propagation, missing digest-length validation and premature key acceptance.

Hosted CI remains pending: Java 17/25 builds, documentation validation and license checks are queued. Dependency review passed; Sonar analysis was skipped. Local validation covered camel-ssh, not the full reactor.

AI-generated review by Codex on behalf of @luigidemasi.

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

Thanks @oscerd. I re-read the changes since my approval (3700546..a1d570a, one new commit, no rebase), and the two findings from @luigidemasi that it addresses.

I went through my previous points:

  • The three findings from the first round, the @revoked-only wording, and the <p> javadoc: still fixed. The new commit does not touch that logic.
  • Unreadable line or resource fails every connection: unchanged, and now also covers malformed hashed hosts. Fine with me, as before.
  • SSHPublicKeyHolder not marked @Deprecated: still optional.

What the new commit does, and what I checked:

  • Hashed entries: a host field that starts with | must be |1|salt|hash, with salt and hash both 20 bytes, otherwise the line is unreadable. HMAC-SHA1 gives 20 bytes, so this is exact. split("\\|", -1) keeps an empty hash as "", which decodes to 0 bytes and is rejected. OpenSSH only skips a bad hashed line, so this is stricter, but it matches the fail-closed rule the docs describe. rejectsEveryServerWhenALineCannotBeRead covers empty, short and long digests and |2|, alone and after a valid entry.
  • Configured host: SshProducer and SshConsumer pass endpoint.getHost() to a new four-argument constructor, and the existing constructors keep the old behaviour, so the public API stays compatible. SshHelper connects with the same configuration.getHost(), so the verifier looks up the name the client was asked to connect to. Brackets are removed and the name is lower-cased before the [host]:port form is built. That fixes the ::1 vs 0:0:0:0:0:0:0:1 case @luigidemasi found.
  • SshComponentKnownHostIPv6Test follows the module's JUnit style, uses MockEndpoint.assertIsSatisfied with no Thread.sleep, and skips itself with an assumption when ::1 is not reachable. The test server binds to the wildcard address, so the test does run where IPv6 is enabled.
  • The docs and the three upgrade-guide notes (4.24, 4.22, 4.18) have the same new sentence.

New findings (non-blocking):

  1. ssh-component.adoc:180 says "an IPv6 address such as ::1 (or [::1] in the endpoint uri)". The javadoc of SshComponentKnownHostIPv6Test says the endpoint uri does not accept an IPv6 address, and the test sets the host with endpoint.setHost("::1"). That matches what I read in core: UnsafeUriCharactersEncoder treats [ and ] as unsafe and encodes them, so new URI(...) in SshConfiguration.configure gets no host. Unless you checked that ssh://user@[::1]:2222 works, I suggest dropping "(or [::1] in the endpoint uri)" from the docs (inline comment). The bracket stripping in toKnownHostsName can stay for setHost("[::1]").
  2. A question, not a blocker: SshClient.setUpDefaultClient() uses SSHD's DefaultConfigFileHostEntryResolver, which reads ~/.ssh/config of the JVM user. With Host db / HostName db.example.com there, Camel connects to db.example.com, but the verifier now looks up db. OpenSSH looks up the HostName (db.example.com). At 3700546 the verifier used the connected address, so it matched OpenSSH in this case. It is a rare setup, and with failOnUnknownHost=true it fails closed. With the default false the server is an unknown host, so any key is accepted with a WARN. If you think it is worth it, the upgrade note could say that the host is matched as configured on the endpoint, without ~/.ssh/config aliases.
  3. Reminder: CAMEL-25644 only has fix version 4.24.0. Add 4.22.2 and 4.18.6 when the backports are merged.

CI: no build has finished on this PR yet. The runs for aa8050b and 3700546 were cancelled. The run for a1d570a failed in the "Get Atlassian dependency version" step (./mvnw help:evaluate -N -f parent/pom.xml), before Maven compiled anything, and the JDK 25 job was cancelled by fail-fast. This PR does not touch parent/pom.xml, so the failure is not caused by the PR. It is an infrastructure failure. The same step failed once before, on 2026-10-09, in an unrelated run. The build needs a re-run before merging.

Checked against the project conventions in CLAUDE.md. This is a rules-and-conventions review and does not replace CodeRabbit, Sourcery or SonarCloud.

Claude Code on behalf of @davsclaus.

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

Comment thread components/camel-ssh/src/main/docs/ssh-component.adoc Outdated
@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • catalog/camel-catalog
  • components/camel-ssh
  • docs
  • dsl/camel-componentdsl
  • dsl/camel-endpointdsl

🔬 Scalpel shadow comparison — Scalpel: 12 of 706 tested, 23 compile-only — current: 12 all tested

Maveniverse Scalpel detected 12 affected modules (current approach: 12).

Skip-tests mode would test 12 modules (5 direct + 11 downstream), skip tests for 23 (generated code, meta-modules)

Modules Scalpel would test (12)
  • camel-azure-files ← downstream of org.apache.camel:camel-ftp
  • camel-ftp ← downstream of org.apache.camel:camel-ssh
  • camel-jbang-mcp ← downstream of org.apache.camel:camel-catalog
  • camel-jbang-plugin-mcp ← downstream of org.apache.camel:camel-jbang-core
  • camel-jbang-plugin-tui ← downstream of org.apache.camel:camel-catalog
  • camel-jbang-plugin-validate ← downstream of org.apache.camel:camel-yaml-dsl-validator
  • camel-jsch ← downstream of org.apache.camel:camel-ssh
  • camel-launcher-container ← downstream of org.apache.camel:camel-launcher
  • camel-ssh ← components/camel-ssh/src/generated/resources/META-INF/org/apache/camel/component/ssh/ssh.json, components/camel-ssh/src/main/docs/ssh-component.adoc, components/camel-ssh/src/main/java/org/apache/camel/component/ssh/ResourceBasedSSHKeyVerifier.java, components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshConfiguration.java, components/camel-ssh/src/main/java/org/apache/camel/component/ssh/SshHelper.java, components/camel-ssh/src/test/java/org/apache/camel/component/ssh/ResourceBasedSSHKeyVerifierTest.java, components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentKnownHostEdDSATest.java, components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentKnownHostIPv6Test.java, components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentKnownHostTest.java, components/camel-ssh/src/test/java/org/apache/camel/component/ssh/SshComponentTestSupport.java, components/camel-ssh/src/test/resources/known_hosts_eddsa, components/camel-ssh/src/test/resources/known_hosts_valid
  • camel-yaml-dsl-validator ← downstream of org.apache.camel:camel-catalog
  • camel-yaml-dsl-validator-maven-plugin ← downstream of org.apache.camel:camel-yaml-dsl-validator
  • camel-zookeeper-master ← downstream of org.apache.camel:camel-ftp
Modules with tests skipped (23)
  • apache-camel
  • camel-allcomponents
  • camel-catalog-console
  • camel-catalog-maven
  • camel-catalog-suggest
  • 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 (39 modules, 6m 26s total)

Total reactor time: 6m 26s

Module Duration Status
Camel :: Launcher 47.6s SUCCESS
Camel :: JBang :: MCP 40.5s SUCCESS
Camel :: SSH 30.8s SUCCESS
Camel :: JBang :: Plugin :: Validate 27.7s SUCCESS
Camel :: Jsch 24.7s SUCCESS
Camel :: YAML DSL 24.2s SUCCESS
Camel :: Catalog :: Camel Catalog 23.3s SUCCESS
Camel :: YAML DSL :: Validator 22.7s SUCCESS
Camel :: Component DSL 21.4s SUCCESS
Camel :: Kamelet Main 18.6s SUCCESS
Camel :: Docs 15.2s SUCCESS
Camel :: JBang :: Plugin :: Testing 13.7s SUCCESS
Camel :: JBang :: Plugin :: Kubernetes 13.0s SUCCESS
Camel :: Assembly 9.0s SUCCESS
Camel :: YAML DSL :: Deserializers 7.3s SUCCESS
Camel :: Catalog :: Camel Route Parser 7.1s SUCCESS
Camel :: Catalog :: Camel Report Maven Plugin 6.7s SUCCESS
Camel :: Azure :: Files 5.8s SUCCESS
Camel :: YAML DSL :: Validator Maven Plugin 4.7s SUCCESS
Camel :: All Components Sync point 4.6s SUCCESS
Camel :: Catalog :: Maven 3.2s SUCCESS
Camel :: YAML DSL :: Maven Plugins 2.5s SUCCESS
Camel :: Catalog :: Suggest (deprecated) 2.2s SUCCESS
Camel :: JBang :: Plugin :: Edit 1.5s SUCCESS
Camel :: Coverage 1.4s SUCCESS
Camel :: JBang :: Plugin :: Generate 1.1s SUCCESS
Camel :: JBang :: Integration tests 0.9s SUCCESS
Camel :: Catalog :: Dummy Component 0.9s SUCCESS
Camel :: Endpoint DSL :: Support 0.8s SUCCESS
Camel :: Catalog :: Console 0.8s SUCCESS
Camel :: JBang :: Main 0.7s SUCCESS
Camel :: Launcher :: Container 0.7s SUCCESS
Camel :: JBang :: Plugin :: MCP 0.7s SUCCESS
Camel :: Endpoint DSL n/a
Camel :: FTP n/a
Camel :: Integration Tests n/a
Camel :: JBang :: Core n/a
Camel :: JBang :: Plugin :: TUI n/a
Camel :: Zookeeper Master n/a

Top 20 slowest modules:

  • Camel :: Launcher (47.6s)
  • Camel :: JBang :: MCP (40.5s)
  • Camel :: SSH (30.8s)
  • Camel :: JBang :: Plugin :: Validate (27.7s)
  • Camel :: Jsch (24.7s)
  • Camel :: YAML DSL (24.2s)
  • Camel :: Catalog :: Camel Catalog (23.3s)
  • Camel :: YAML DSL :: Validator (22.7s)
  • Camel :: Component DSL (21.4s)
  • Camel :: Kamelet Main (18.6s)
  • Camel :: Docs (15.2s)
  • Camel :: JBang :: Plugin :: Testing (13.7s)
  • Camel :: JBang :: Plugin :: Kubernetes (13.0s)
  • Camel :: Assembly (9.0s)
  • Camel :: YAML DSL :: Deserializers (7.3s)
  • Camel :: Catalog :: Camel Route Parser (7.1s)
  • Camel :: Catalog :: Camel Report Maven Plugin (6.7s)
  • Camel :: Azure :: Files (5.8s)
  • Camel :: YAML DSL :: Validator Maven Plugin (4.7s)
  • Camel :: All Components Sync point (4.6s)

⚙️ View full build and test results

@davsclaus
davsclaus dismissed gnodet-bot’s stale review October 15, 2026 05:52

Outdated: this review was on aa8050b. gnodet-bot's re-review on 3700546 found all its findings addressed. A re-review of the current head a1d570a is requested below. (Claude Code on behalf of @davsclaus)

@davsclaus
davsclaus requested a review from gnodet-bot October 15, 2026 05:52
@davsclaus

Copy link
Copy Markdown
Contributor

@gnodet-bot please re-review the current head a1d570a. Your last review was on 3700546, and one commit has been added since: the configured host is kept for the known_hosts lookup (IPv6 included), and malformed hashed entries now fail closed. I dismissed your CHANGES_REQUESTED review on aa8050b because your re-review on 3700546 already found its findings addressed.

@oscerd one thread is still open: my suggestion on ssh-component.adoc line 181 to drop "(or [::1] in the endpoint uri)", since an IPv6 address in the endpoint uri does not reach SshConfiguration as a host. Please apply it or reply there.

Claude Code on behalf of @davsclaus

When ~/.ssh/config gives a HostName for the host configured on the
endpoint, SSHD connects to that HostName, and OpenSSH looks the server
up by it. The verifier now uses the host name or address the client
connects to, never resolved through DNS, as before the previous commit.
Only an IPv6 address configured on the endpoint keeps its written
spelling, because the connected address writes it in its full form.

The docs no longer say that an IPv6 address can be given in the
endpoint uri, which does not accept one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>

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

Thanks @oscerd. I re-read the changes since my approval (a1d570a..1d26dce, 1 new commit):

  • The docs no longer say that an IPv6 address can be given in the endpoint uri, which resolves my thread.
  • The verifier now looks the server up by the host name the client connects to, so a HostName from ~/.ssh/config is used as OpenSSH does. I checked SSHD 2.20.0: AbstractClientSession.checkKeys() passes the target server address (SshdSocketAddress.toInetSocketAddress()) to the verifier when it is set, and toSshdSocketAddress takes InetSocketAddress.getHostString(), so the name is never taken from a reverse lookup. An IPv6 address configured on the endpoint keeps its written spelling, as before.
  • looksUpTheHostNameTheClientConnectsTo covers the HostName case, and the three upgrade-guide notes (4.18, 4.22, 4.24) say the same.

CI is green.

Claude Code on behalf of @davsclaus.

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

@luigidemasi luigidemasi 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 previously reported findings are addressed. However, I found one remaining major issue in the interaction between SSH config aliases and IPv6 host-key lookup.

P1: Preserve the effective IPv6 HostName when checking known_hosts

In ResourceBasedSSHKeyVerifier.toKnownHostsName(), the IPv6 spelling is preserved only when the endpoint’s configured host contains :. An endpoint using an alias such as review-ipv6, with this SSH configuration, bypasses that branch:

Host review-ipv6
    HostName ::1

The verifier then looks up [0:0:0:0:0:0:0:1]:port, missing a valid [::1]:port entry.

I reproduced this through the Camel SSH producer:

  • With the default failOnUnknownHost=false, a different server key passed verification and the server received the synthetic password.
  • With failOnUnknownHost=true, the legitimate key was rejected.
  • Using the expanded address in known_hosts restored correct key checking.

This also reproduces against the implementation before this PR. It is an unresolved pre-existing case that my earlier review missed, rather than a regression introduced by this commit.

Please:

  1. Preserve the effective HostName selected by SSHD before socket-address conversion loses its IPv6 spelling, and use it consistently for producer and consumer verification.
  2. Add connection-level regression coverage for an alias resolving to compressed IPv6, with matching and different keys under both values of failOnUnknownHost.
  3. Assert that rejected peers receive no password, while retaining the existing direct-IPv6 and hostname-alias coverage.

Validation: only camel-ssh was built; all 66 tests passed. Hosted Java 17/25 builds, documentation, dependency and license checks passed; Sonar was skipped.

AI-generated review by Codex on behalf of @luigidemasi.

…gives

An alias in ~/.ssh/config whose HostName is an IPv6 address, such as
HostName ::1, was looked up through the connected address, which writes
the address in its full form, so an entry for [::1]:port was not found.
The verifier now resolves the configured host through the host
configuration that the client of the session used for the connection
(~/.ssh/config by default, or the resolver of a custom client builder),
and uses the HostName it gives, as written; without an entry, it uses
the configured host as written.

The connection tests cover an alias resolving to ::1 and an alias
resolving to a host name, and assert that a server whose key is
rejected receives no credentials.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
@oscerd

oscerd commented Oct 15, 2026

Copy link
Copy Markdown
Contributor Author

@luigidemasi fixed in ef7e70d:

  1. Effective HostName. The verifier now asks the session's client for the host configuration that SSHD used for the connection (ClientFactoryManager.getHostConfigEntryResolver(): ~/.ssh/config by default, or the resolver of a custom clientBuilder). It uses the HostName that configuration gives for the configured host, as it is written. Without an entry, it uses the configured host as written.
    • The producer and the consumer both pass the configured host, so both verify the same way.
    • The connected address is used only by the existing constructors.
  2. Alias to compressed IPv6. SshComponentKnownHostIPv6Test now has an alias review-ipv6, which the client's host configuration resolves to HostName ::1.
    • It runs with the listed key and another key, under both values of failOnUnknownHost, next to the four direct ::1 cases.
    • On 1d26dce, the two alias cases you describe fail: the listed key is rejected with true, and another key is accepted with false.
  3. No credentials to rejected peers. Every connection test now asserts whether the test server received credentials. Rejected peers receive none, and accepted ones do.
    • The test server records both the password and the public-key method, because the client also offers the ~/.ssh identities of the machine it runs on.
    • The hostname alias (db-alias → HostName localhost) is covered in SshComponentKnownHostTest.
    • ResourceBasedSSHKeyVerifierTest covers both aliases through a session whose client has the resolver.

Claude Code on behalf of Andrea Cosentino (@oscerd)

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

This PR rewrites the camel-ssh known_hosts verification to implement correct OpenSSH semantics with a fail-closed design. Solid work.

What was reviewed:

  • The new DefaultKnownHostsVerifier correctly handles @revoked entries — a host appearing only in @revoked entries is treated as unknown (not blocked), matching OpenSSH behaviour
  • isSameKey() returns false for null keys, so an unsupported key type in a revoked entry doesn't create a bypass — the host falls to the failOnUnknownHost check
  • matchesPattern() implements a standard two-pointer wildcard algorithm for */? — correct for edge cases
  • effectiveHostName() resolves IPv6 aliases through HostConfigEntryResolver.resolveEffectiveHost()
  • Thread safety looks sound: verifyServerKey uses only local variables (hostListed, keyListed, sameKey) and immutable instance fields
  • The rejectsEveryServerWhenALineCannotBeRead test covers the critical fail-closed path (malformed line after a valid matching entry)
  • Migration notes are duplicated across the 4.18, 4.22, and 4.24 upgrade guides — appropriate given the security impact
  • Catalog JSON changes appear auto-generated from updated Javadoc descriptions

No issues found. ✅

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@luigidemasi luigidemasi 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 IPv6-alias issue from my previous review is fixed. The original Camel producer reproduction now rejects different server keys before transmitting credentials, under both values of failOnUnknownHost.

Required / P2: Fail closed when effective-host lookup fails

In ResourceBasedSSHKeyVerifier.effectiveHostName(), the new lookup catches IOException and RuntimeException, logs a warning, and returns the endpoint’s original host.

For an alias, that fallback changes the identity being checked. The connection was established using the resolved target, but verification now searches known_hosts for the alias. If only the target is listed, the default failOnUnknownHost=false accepts a different key.

I reproduced this through the Camel producer with a resolver that:

  1. Successfully resolves the alias to localhost for connection establishment.
  2. Throws an injected IOException when the verifier resolves it again.

The current head transmitted the synthetic password to a server presenting a different key. The preceding commit rejected that key. This reproduction requires a resolver failure; it does not demonstrate that a remote peer alone can trigger the failure.

Please:

  1. Retain the effective target selected for that connection, preserving its spelling before socket-address conversion, and use that identity for verification.
  2. Reject verification if the effective target cannot be established reliably. A lookup failure must not fall through to permissive unknown-host acceptance.
  3. Add regression coverage for this failure path, including both values of failOnUnknownHost, and assert that a different key receives no credentials. Retain the working IPv6-alias and hostname-alias tests.

Validation: only camel-ssh was built; all 72 tests passed. Hosted Java 17/25 builds, documentation, dependency and license checks passed; Sonar was skipped.

AI-generated review by Codex on behalf of @luigidemasi.

… connection

The verifier resolved the configured host a second time, and fell back
to the configured alias when that lookup failed, so a resolver that
answered for the connection but not for the verifier made the verifier
look up another host than the one connected to.

The producer and the consumer now resolve the host configuration once,
as SshClient.connect(username, host, port) does, connect with that entry
and put it in the connection context. The verifier reads it from the
session and uses its HostName as written, without resolving again; a
host reached through a jump host uses the TARGET_SERVER that SSHD keeps
as written, and the jump host its own address. A host configuration that
cannot resolve the host now fails the connection before any server is
contacted. The constructor that took the configured host is removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
@oscerd

oscerd commented Oct 15, 2026

Copy link
Copy Markdown
Contributor Author

@luigidemasi fixed in 593f670, without a second lookup:

  1. One resolution per connection. SshHelper resolves the host configuration once with the client's resolver, as SshClient.connect(username, host, port) does internally. It connects with that entry (client.connect(entry, context, null)) and puts the same entry in the connection context (ResourceBasedSSHKeyVerifier.HOST_CONFIG_ENTRY).
    • The verifier reads the entry from session.getConnectionContext() and never asks the resolver. It uses the entry's HostName as written.
    • A session reached through a jump host uses TARGET_SERVER, which SSHD keeps as written.
    • The configured-host constructor from the previous commits is gone; the producer and the consumer are back to the existing constructor.
  2. Fail closed when the target can't be established. A resolver that cannot resolve the host now fails the connection itself, before any server is contacted. Nothing reaches the verifier or the unknown-host branch.
    • This also fixes the jump hops: ef7e70d checked them against the name of the target, and they are now checked against their own address.
  3. Tests:
    • The alias routes in SshComponentKnownHostIPv6Test use a resolver that answers only once and throws afterwards, which is your reproduction. They run with the listed key and another key, under both values of failOnUnknownHost. On ef7e70d, the alias cases with the listed key (true) and with another key (false) fail.
    • SshComponentKnownHostTest adds a resolver that always fails, under both values: the exchange fails and the server receives no credentials. The hostname-alias tests are kept.
    • ResourceBasedSSHKeyVerifierTest covers the connection-context lookup (::1, [::1], a host name, no context) and a target reached through a jump host versus the jump host itself.

Claude Code on behalf of Andrea Cosentino (@oscerd)

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

✅ Review of commit 593f670 (fix for CAMEL-25644)

The commit correctly resolves the P2 security finding. The architecture change from "resolve twice with fallback" to "resolve once at connection time, store in session context" is fundamentally sound.

Key points verified:

  • resolveHostConfig() is called before client.connect(). If it throws IOException, the exception propagates immediately — no TCP connection is established and no server key verification occurs. This eliminates the fallback-to-alias security bug.
  • HOST_CONFIG_ENTRY is correctly plumbed via AttributeRepository.ofKeyValuePair(...) into the session context, and retrieved in toKnownHostsName() via session.getConnectionContext().
  • The ProxyJump guard is correct: jump host sessions do not have TARGET_SERVER set; target sessions do. The condition hostConfig.getProxyJump() == null || hostConfig.getProxyJump().isEmpty() correctly prevents using the target's HostName for jump host verification.
  • The 4-arg constructor removal is not a public API break — it was introduced earlier in this same PR and never existed on main.
  • Test coverage is thorough: brokenAlias tests confirm the P2 regression scenario (IOException → no connection, no credentials sent); resolvingOnce() structurally asserts the resolver is called exactly once.

No new issues found.

This review was generated by an AI agent, Hermès 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.

Thanks @oscerd. I re-read the changes since my approval (1d26dce..593f670, 2 new commits, no rebase), and the two findings from @luigidemasi they address:

  • IPv6 alias (P1): fixed. The verifier no longer uses the connected address, which writes ::1 in full, but the HostName of the host configuration the connection was made with, as written. SshComponentKnownHostIPv6Test covers an alias resolving to ::1 with the listed key and another key, under both values of failOnUnknownHost.
  • Fallback when the lookup fails (P2): fixed by design in 593f670. SshHelper resolves the host configuration once, connects with that entry and puts it in the connection context, and the verifier reads it from session.getConnectionContext() without resolving again. I checked SSHD 2.20.0: resolveHostConfig builds the same synthetic entry as SshClient.resolveHost. A resolver error now fails the exchange before any server is contacted, and the brokenAlias tests show the server gets no credentials under either failOnUnknownHost value.
  • Jump hosts: the target uses TARGET_SERVER, which SSHD sets for a proxied session, and a hop with a ProxyJump falls back to its own address. ResourceBasedSSHKeyVerifierTest covers both.
  • The 4-arg constructor added earlier in this PR is gone, so there is no API change against main, and the docs and the 4.18/4.22/4.24 upgrade guide entries still match. The new assertions that a rejected peer receives no credentials are a good addition.

No new findings. Optional: HOST_CONFIG_ENTRY is public with @since 4.24. If this is backported to 4.18.x/4.22.x, it could be package-private, as only SshHelper sets it.

CI: the build on JDK 17 and 25 is still running on 593f670; doc validation, license and dependency review are green. @luigidemasi's change request is on ef7e70d and still needs his re-review.

Claude Code on behalf of @davsclaus.

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

@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

✅ Generated files are up to date

An earlier CI run reported uncommitted generated changes; the latest run no longer does.

Signed-off-by: Andrea Cosentino <ancosen@gmail.com>

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

Re-reviewed 76753a9, including the fix in 593f670. The latest resolver-failure finding is addressed, and I have no remaining blocking findings from this review.

The producer and consumer now resolve the host configuration once, connect with that result, and retain it in the session connection context for host-key verification. The verifier no longer performs a second lookup or falls back to the alias after a lookup error. An initial resolution failure stops connection establishment.

Verification:

  • The original resolver-failure reproduction fails against the preceding implementation and passes against the new sources. Each tested connection resolves its target exactly once.
  • Different server keys receive no password under either value of failOnUnknownHost; matching keys reach authentication. Initial resolver failures send no credentials.
  • The independent IPv6-alias reproduction still passes. Two updated connection tests fail against the preceding implementation.
  • All 74 camel-ssh tests passed, with no skips, in a standalone harness compiling the current production, generated and test Java sources against the previously working 4.23.0-SNAPSHOT dependency set.

Validation limitation: the normal module-only Maven build stopped before compilation because camel-package-maven-plugin:4.24.0-SNAPSHOT was unavailable locally. The harness result is not a successful Maven build with the current 4.24 snapshot dependencies. No full reactor build was run.

Hosted CI at submission: Java 17/25 builds, documentation validation and license checks remain queued; dependency review passed; Sonar analysis was skipped.

AI-generated review by Codex on behalf of @luigidemasi.

@davsclaus davsclaus added this to the 4.24.0 milestone Oct 16, 2026
@davsclaus davsclaus added the bug Something isn't working label Oct 16, 2026
@davsclaus

Copy link
Copy Markdown
Contributor

Approved and ready to merge, but it now conflicts with main in docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc: several PRs merged today added entries to the 4.23 → 4.24 section. Could you rebase on main? It can be merged once CI is green again.

Claude Code on behalf of Claus Ibsen

@gnodet

gnodet commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

🔄 Backport Bot

This bugfix targets main and may need porting to:

  • camel-4.22.x

Add a port/<branch> label to automatically create a backport PR for that branch.

Backport PRs will be created automatically on merge (once a port label is added). Comment /port to create them immediately.

ℹ️ If you push additional commits after /port, use /port again to update the port PRs.

@davsclaus

Copy link
Copy Markdown
Contributor

@oscerd this is approved and green, but it now has a merge conflict with main. Could you rebase it? I will merge it once it is green again.

Claude Code on behalf of Claus Ibsen

oscerd and others added 3 commits October 18, 2026 12:34
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>

# Conflicts:
#	docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
camel-4.22.2 has been cut, so the camel-4.22.x backport of this change
ships in 4.22.3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>
Signed-off-by: Andrea Cosentino <ancosen@gmail.com>

# Conflicts:
#	docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
#	docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
@oscerd

oscerd commented Oct 19, 2026

Copy link
Copy Markdown
Contributor Author

@davsclaus the conflict is resolved. I merged the current main into the branch instead of rebasing, as in the earlier rounds, so the commits you approved are unchanged and nothing was force-pushed. The PR is squash-merged, so the result is the same.

No code changed. On the new head, the full reactor build (mvn clean install -DskipTests -DskipITs) succeeds and regenerates nothing, and the 74 camel-ssh tests pass. CI is running.

Claude Code on behalf of Andrea Cosentino (@oscerd)

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

Thanks @oscerd. I re-read the changes since my approval of 76753a9: two merges of main and e182197.

  • The merges bring in no change of the PR's own: the lines the PR changes against main are the same as at 76753a9.
  • e182197 moves the camel-ssh note in the 4.22 guide from the 4.22.1 to 4.22.2 section to "Upgrading from 4.22.2 to 4.22.3", because 4.22.2 has been released without it. The text is unchanged. The 4.18 note stays under 4.18.6, and the 4.24 note is in place. This matches where the backports will ship.

The build jobs are still running on the merge with the latest main.

Claude Code on behalf of Claus Ibsen

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

LGTM

@oscerd
oscerd merged commit 7bcdc00 into apache:main Oct 19, 2026
7 checks passed
@oscerd
oscerd deleted the fix/CAMEL-25644 branch October 19, 2026 13:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants