CVE-2026-59324
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
Spring Integration is the Spring portfolio project that brings the Enterprise Integration Patterns to Spring applications. It provides a lightweight messaging framework of channels, endpoints, transformers and routers, together with channel adapters for protocols and technologies such as files, FTP, HTTP, JDBC, JMS, AMQP, SMB and ZeroMQ.
An Information Exposure vulnerability (CVE-2026-59324) has been identified in the fluxTransform() operator of the Java DSL, which allows one user's response payload to be delivered to another user's reply channel when the supplied function is asynchronous or reorders elements.
Per OWASP, such failures "typically lead to unauthorized information disclosure" or modification of data beyond a user's limits. Both happen here with no permission check involved — the framework's own header handling carries one user's response across the boundary, producing what the advisory calls "cross-request information disclosure and reply mis-routing." The CVSS v3.1 base score for this vulnerability is 8.2 (High) with vector AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N.
This issue affects the reactive Java DSL of Spring Integration. A deployment is exposed only if a flow calls fluxTransform() with a function that emits raw payloads instead of Message instances, and that function is asynchronous, concurrent, or reorders elements — for example a flatMap over a remote call. A function that emits Message instances itself is unaffected, and so is a synchronous one-in-one-out function, because the shared holder is then always read in the same order it was written.
Details
Module Info
- Product: Spring Integration
- Affected packages:
org.springframework.integration:spring-integration-core- Affected versions: >=7.1.0 <7.1.1, >=7.0.0 <7.0.6, >=5.1.0 <=6.5.10
- GitHub repository: https://github.com/spring-projects/spring-integration
- Published packages: https://central.sonatype.com/artifact/org.springframework.integration/spring-integration-core
- Package manager: Maven
- Fixed in:
- NES for Spring Integration: 5.5.x, 6.2.x, 6.3.x, 6.4.x, 6.5.x
- OSS Spring Integration 7.0.6, 7.1.1
Vulnerability Info
The vulnerability is in Transformers and BaseIntegrationFlowDefinition in the spring-integration-core Java DSL. BaseIntegrationFlowDefinition.fluxTransform() is the public entry point: it accepts a function that may emit plain payloads instead of Message instances, and delegates to the package-private helper Transformers.transformWithFunction(), where the defect lives. To rebuild a reply for a raw payload, that helper must know which request the payload came from, and it tracks that in a single holder placed in the Reactor context:
static <I, O> Flux<Message<O>> transformWithFunction(
Publisher<Message<I>> publisher,
Function<? super Flux<Message<I>>, ? extends Publisher<O>> fluxFunction) {
return Flux.from(publisher)
.flatMap(
message ->
Mono.deferContextual(
ctx -> {
ctx.get(RequestMessageHolder.class).set(message);
return Mono.just(message);
}))
.transform(fluxFunction)
.flatMap(
data ->
data instanceof Message<?>
? Mono.just((Message<O>) data)
: Mono.deferContextual(
ctx -> Mono.just(ctx.get(RequestMessageHolder.class).get()))
.map(
requestMessage ->
MessageBuilder.withPayload(data)
.copyHeaders(requestMessage.getHeaders())
.build()))
.contextWrite(ctx -> ctx.put(RequestMessageHolder.class, new RequestMessageHolder()));
}
private static final class RequestMessageHolder extends AtomicReference<Message<?>> {
}
The Reactor context is established once per subscription, not once per element, so a single RequestMessageHolder is shared by every message flowing through the same FluxMessageChannel subscription. Each inbound message overwrites it, and the downstream stage reads whatever value happens to be there when a payload arrives. As soon as the user function is asynchronous, concurrent or reordering, for example a flatMap over a remote call, the reply is built with copyHeaders() from a different in-flight request, so replyChannel, errorChannel, correlationId and any propagated security or tenant headers belong to another user. The response is then delivered to that other user's reply channel, which discloses the payload across requests and mis-routes the exchange.
This vulnerability was introduced in 2018 with Spring Integration 5.1.0, when the fluxTransform() operator was added to the Java DSL.
Mitigation
Only recent versions of Spring Integration receive community support. Older lines are End-of-Life and will not receive public updates to address this issue.
Note that the fix changes behaviour rather than restoring it: fluxTransform() no longer infers which request a raw payload belongs to, and instead throws IllegalStateException for any element the supplied function emits that is not already a Message. Applications whose function emits bare payloads must be updated to emit Message instances, as in the first mitigation below.
Users of the affected components should apply one of the following mitigations:
- Declare the
fluxTransform()function asFunction<? super Flux<Message<I>>, ? extends Publisher<Message<O>>>so that it emits messages itself and no reply headers are copied from an unrelated request. - Upgrade to a currently supported version of Spring Integration.
- Leverage a commercial support partner like HeroDevs for post-EOL security support.