You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Andrea Cosentino (Jira)" <ji...@apache.org> on 2026/08/23 10:18:00 UTC

[jira] [Created] (CAMEL-24429) camel-as2 - per-request security material outlives the request in ResponseMDN and the listener context

Andrea Cosentino created CAMEL-24429:
----------------------------------------

             Summary: camel-as2 - per-request security material outlives the request in ResponseMDN and the listener context
                 Key: CAMEL-24429
                 URL: https://issues.apache.org/jira/browse/CAMEL-24429
             Project: Camel
          Issue Type: Bug
          Components: camel-as2
            Reporter: Andrea Cosentino
            Assignee: Andrea Cosentino
             Fix For: 4.23.0


Two places keep per-request state where it can be observed by a later or concurrent request.

*ResponseMDN* holds the security material in mutable instance fields and overwrites them per request:

{code:java}
private AS2SignatureAlgorithm signingAlgorithm;
private Certificate[] signingCertificateChain;
private PrivateKey signingPrivateKey;
private PrivateKey decryptingPrivateKey;
private Certificate[] validateSigningCertificateChain;
private boolean keysAreDynamic = false;
...
if (this.keysAreDynamic) {
    this.signingAlgorithm = (AS2SignatureAlgorithm) context.getAttribute(AS2ServerConnection.AS2_SIGNING_ALGORITHM);
    this.signingCertificateChain = (Certificate[]) context.getAttribute(...AS2_SIGNING_CERTIFICATE_CHAIN);
    this.signingPrivateKey = (PrivateKey) context.getAttribute(...AS2_SIGNING_PRIVATE_KEY);
    this.decryptingPrivateKey = (PrivateKey) context.getAttribute(...AS2_DECRYPTING_PRIVATE_KEY);
    this.validateSigningCertificateChain = (Certificate[]) context.getAttribute(...AS2_VALIDATE_SIGNING_CERTIFICATE_CHAIN);
}
{code}

The instance is registered once on the shared HttpProcessor, so it is shared across requests. The assignment block is not inside the class's lock, and the values persist after the request that set them. A deployment hosting two partners on different paths with different keys can therefore have one request's MDN signed with the other partner's key.

*AS2ServerConnection* creates the HttpContext once outside the request loop:

{code:java}
final HttpContext context = HttpCoreContext.create();
try {
    while (!Thread.interrupted()) {
        this.httpService.handleRequest(this.serverConnection, context);
        ...
        String recipientAddress = coreContext.getAttribute(AS2AsynchronousMDNManager.RECIPIENT_ADDRESS, String.class);
{code}

RECIPIENT_ADDRESS and ASYNCHRONOUS_MDN set while handling one request are still present on the next iteration, so a later request that does not request an asynchronous MDN can trigger a resend to the previous request's address.

Proposal: keep the dynamically loaded keys and chains in local variables (or in the HttpCoreContext) for the duration of process() rather than in instance fields, and remove RECIPIENT_ADDRESS/ASYNCHRONOUS_MDN from the context after the send block - or create a fresh context per request. A test that drives two requests with different key material through one connection would cover both.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)