CVE-2026-41847

Authorization Bypass
Affects
Spring Framework
in
Spring
No items found.
Versions
>=5.3.0 <=5.3.48
Exclamation circle icon
Patch Available

This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.

Overview

Spring Framework is the foundational application framework for the Java platform, providing the core dependency-injection container as well as the web stacks that most Java server applications are built on. One of those stacks is Spring WebFlux, the reactive, non-blocking web framework, which offers a functional routing model in addition to annotated controllers. For Kotlin users, WebFlux ships a Kotlin Router DSL (router { ... } in org.springframework.web.reactive.function.server) that lets developers declare routes and cross-cutting filter blocks in idiomatic Kotlin. Filters in this DSL are the natural place to implement security concerns: authenticating a request, attaching a resolved principal, wrapping the ServerRequest, or sanitizing headers before the request reaches a handler.

A medium-severity vulnerability (CVE-2026-41847) has been identified in the reactive Kotlin Router DSL filter extension. When a filter passes a modified ServerRequest to the downstream handler (for example a wrapped request carrying an authenticated principal or sanitized headers), the DSL discards that modified request and invokes the handler with the original, unmodified request instead. Any security-relevant change a filter makes to the request is silently dropped, so a downstream handler that relies on the filter having enriched or sanitized the request receives the request exactly as the client sent it. In an application that uses a Kotlin DSL filter to enforce or shape security state on the request, this allows that enforcement to be bypassed.

Per OWASP, access control enforces policy such that users cannot act outside of their intended permissions, and failures typically lead to unauthorized information disclosure, modification, or destruction of data, or performing a business function outside the user's limits. A filter whose request modifications never reach the handler is exactly such a failure: the access-control decision the filter intended to impose is not the decision the handler actually sees.

This issue affects Spring Framework >=5.3.0 <=5.3.48.

Details

Module Info

Vulnerability Info

The vulnerability is in the filter extension of the reactive Kotlin Router DSL, defined in RouterFunctionDsl in the spring-webflux module (org.springframework.web.reactive.function.server). The DSL exposes filter so that a Kotlin application can register a function over every route built by the router. The filter function is handed the incoming ServerRequest and a continuation it can call to invoke the rest of the chain, and it is expected to be able to pass a modified request into that continuation.

Pre-fix, the DSL wired the continuation incorrectly. The inner lambda ignored the request the filter forwarded and instead re-used the request captured from the enclosing scope:

fun filter(filterFunction: (ServerRequest, (ServerRequest) -> Mono<ServerResponse>) -> Mono<ServerResponse>) {
    builder.filter { request, next ->
        filterFunction(request) {
            next.handle(request)
        }
    }
}

The lambda parameter passed by the filter (available as it) is the request the filter wants the handler to process. By calling next.handle(request) rather than next.handle(it), the DSL always handed the underlying HandlerFunction the original request. Any wrapping or mutation a filter performed (for example replacing the principal, decorating headers, or substituting a ServerRequest wrapper) was therefore discarded, and the handler executed against the unmodified client request. When the filter is performing a security function, the security state it established does not reach the handler, and the protection can be bypassed.

The defect was introduced in Spring Framework 5.2.0, where the filter extension was added to the Kotlin Router DSL (the function is documented @since 5.2). It was carried unchanged through the entire 5.2.x and 5.3.x lines. The advisory's stated range floor of 5.3.0 reflects Spring's currently-supported scope; the older 5.2.x line is also affected. The coroutine variant of the DSL (CoRouterFunctionDsl.filter, used by coRouter { ... }) is not affected: it already forwards the filter's request argument to the handler.

Steps To Reproduce

1. Create a Spring WebFlux application (Spring Framework 5.3.x) and define routes with the Kotlin Router DSL, using a filter block that wraps the incoming request to attach security state. For example, wrap the ServerRequest so it exposes an authenticated principal:

   class AuthenticatingRequest(
       delegate: ServerRequest,
       private val authenticated: Principal
   ) : ServerRequest by delegate {
       override fun principal(): Mono<Principal> = Mono.just(authenticated)
   }

   val routes = router {
       GET("/whoami") { request ->
           request.principal()
               .map { ServerResponse.ok().bodyValue("user=${it.name}") }
               .flatMap { it }
               .switchIfEmpty(ServerResponse.status(401).build())
       }
       filter { request, next ->
           val enriched = AuthenticatingRequest(request, NamedPrincipal("alice"))
           next(enriched)
       }
   }


2. Send a request to GET /whoami.

3. Observe the response. On an affected version the handler sees the original request, so request.principal() is empty and the endpoint returns 401, even though the filter forwarded an enriched request carrying the alice principal. The request modification made by the filter never reached the handler.

4. Repeat against a fixed build (Spring Framework 6.0.0, or a HeroDevs NES build). The handler now receives the request the filter forwarded, request.principal() resolves to alice, and the endpoint returns user=alice. This demonstrates that on affected versions a security modification applied in a Kotlin DSL filter is silently dropped.

Mitigation

Only recent versions of Spring Framework receive community support and updates. The 5.2.x and 5.3.x lines are End-of-Life for open-source support, and no public OSS release of those lines contains a fix for this vulnerability.

Users of the affected components should apply one of the following mitigations:

  • Upgrade to a currently supported version of Spring Framework. The fix is present in the OSS 6.0.0 release and all later 6.x releases.
  • As an interim measure on an affected deployment, do not rely on the reactive Kotlin Router DSL filter block to apply security-relevant request modifications. Implement such concerns with a mechanism that propagates correctly on the affected version, for example a WebFilter registered on the reactive web chain, or the coroutine coRouter DSL whose filter forwards the modified request correctly.
  • Leverage a commercial support partner like HeroDevs for post-EOL security support through Never-Ending Support (NES) for Spring Framework.
Vulnerability Details
Severity
Level
CVSS Assessment
Low
>=0 <4
Medium
>=4 <6
High
>=6 <8
Critical
>=8 <10
Medium
ID
CVE-2026-41847
PROJECT Affected
Spring Framework
Versions Affected
>=5.3.0 <=5.3.48
NES Versions Affected
Published date
June 11, 2026
≈ Fix date
June 10, 2026
Category
Authorization Bypass
Vex Document
Download VEXHow do I use it?
Sign up for the latest vulnerability alerts fixed in
NES for Spring
Rss feed icon
Subscribe via RSS
or

By clicking “submit” I acknowledge receipt of our Privacy Policy.

Thanks for signing up for our Newsletter! We look forward to connecting with you.
Oops! Something went wrong while submitting the form.