CVE-2026-41839
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 dependency injection, web stacks, data access, and more. Its reactive web stack, Spring WebFlux, ships its own server-side session abstraction in the spring-web module: a WebSession whose lifecycle is managed by DefaultWebSessionManager, whose ID is read from and written to the client by a WebSessionIdResolver (by default CookieWebSessionIdResolver), and whose state is persisted by a WebSessionStore (by default InMemoryWebSessionStore). A security layer rotates the session ID at authentication time by calling WebSession.changeSessionId(), which is the standard defense against session fixation.
A low-severity vulnerability (CVE-2026-41839) has been identified in WebFlux session handling. A WebFlux application whose session cookie is scoped to a parent domain can have a known, attacker-supplied session ID promoted into an authenticated user's session, allowing an attacker who controls a compromised sibling subdomain (for example, via cross-site scripting) to exchange a known session ID for that of an authenticated user and ride the victim's authenticated session.
Per OWASP, session fixation is an attack that permits an attacker to hijack a valid user session by exploiting a limitation in the way the web application manages the session ID: when authenticating a user, the vulnerable application does not assign a new session ID, making it possible to use an existing one. The attack consists of obtaining a valid session ID, inducing a user to authenticate with that session ID, and then hijacking the user-validated session through knowledge of the session ID used.
The CVSS v3.1 base score for this vulnerability is 4.2 (Low) with vector AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N. The attack vector is Network because the attacker operates from a compromised subdomain over the network, attack complexity is High because the attack requires a compromised sibling subdomain plus a victim who authenticates while the fixed session ID is in place, and no privileges on the target application are required. User interaction is Required (the victim must authenticate), the scope is Unchanged, and the impact is Low to both Confidentiality and Integrity because the attacker is confined to the authority of the hijacked session, with no availability impact.
This issue affects Spring Framework >=5.3.0 <=5.3.48, >=6.1.0 <=6.1.27, >=6.2.0 <=6.2.18, and >=7.0.0 <=7.0.7.
Details
Module Info
- Product: Spring Framework
- Affected packages: spring-web
- Affected versions: >=5.3.0 <=5.3.48, >=6.1.0 <=6.1.27, >=6.2.0 <=6.2.18, >=7.0.0 <=7.0.7
- GitHub repository: https://github.com/spring-projects/spring-framework
- Published packages: https://central.sonatype.com/artifact/org.springframework/spring-web
- Package manager: Maven
- Fixed in:
- NES for Spring Framework 5.3.x, 6.1.x
- Spring Framework 7.0.8, 6.2.19 (OSS)
Vulnerability Info
The vulnerability is in the WebFlux server-side session machinery in the spring-web module, in org.springframework.web.server.session. WebFlux session id rotation, the standard session-fixation defense, is implemented by WebSession.changeSessionId(), backed in the default store by InMemoryWebSession.changeSessionId() in InMemoryWebSessionStore:
@Override
public Mono<Void> changeSessionId() {
return Mono.<Void>defer(() -> {
String currentId = this.id.get();
InMemoryWebSessionStore.this.sessions.remove(currentId);
String newId = String.valueOf(idGenerator.generateId());
this.id.set(newId);
InMemoryWebSessionStore.this.sessions.put(this.getId(), this);
return Mono.empty();
})
.subscribeOn(Schedulers.boundedElastic())
.publishOn(Schedulers.parallel())
.then();
}
Session ID resolution and persistence are driven by DefaultWebSessionManager. On each request it asks the configured WebSessionIdResolver (default CookieWebSessionIdResolver) for the session ID presented by the client, retrieves the matching session from the store, and writes the ID back on response commit:
private Mono<WebSession> retrieveSession(ServerWebExchange exchange) {
return Flux.fromIterable(getSessionIdResolver().resolveSessionIds(exchange))
.concatMap(this.sessionStore::retrieveSession)
.next();
}
private Mono<Void> save(ServerWebExchange exchange, WebSession session) {
List<String> ids = getSessionIdResolver().resolveSessionIds(exchange);
...
if (ids.isEmpty() || !session.getId().equals(ids.get(0))) {
this.sessionIdResolver.setSessionId(exchange, session.getId());
}
return session.save();
}
The default cookie resolver binds the server-side WebSession to the session ID presented by the client. Cookies are scoped per registrable domain, so a cookie set for a parent domain (example.com) is sent to every subdomain (app.example.com), and a compromised sibling subdomain can write such a cookie into the victim's browser, including by way of cross-site scripting. An attacker therefore pre-seeds a known session ID into the victim's browser. When the WebFlux application does not force a fresh, server-generated ID at the moment the user authenticates, the authenticated principal stays bound to the attacker-known ID. The attacker then replays that same ID and is admitted to the now-authenticated session, gaining the victim's authenticated authority without ever proving the victim's credentials.
The fix tightens WebFlux session ID handling so that a known or attacker-supplied ID cannot be carried over into an authenticated session, ensuring a server-generated ID is established for the authenticated session. The accompanying hardening on the same rotation path serializes the ID change so that the store's mapping is updated atomically. The fixed releases are Spring Framework 7.0.8 and 6.2.19 (OSS). The vulnerable WebFlux session handling has existed since the org.springframework.web.server package was introduced with WebFlux in Spring Framework 5.0, so the advisory's 5.3.0 lower bound reflects Spring's currently supported scope rather than the point of introduction. Spring Framework 4.3.x and earlier do not ship WebFlux and are not affected.
Steps To Reproduce
1. Build a Spring WebFlux application (Spring Framework 6.2.18 or any other affected pre-fix version) that uses the default WebFlux session support and authenticates users, with the session cookie scoped to a parent domain so that it is shared across subdomains:
@Bean
public WebSessionManager webSessionManager() {
DefaultWebSessionManager manager = new DefaultWebSessionManager();
CookieWebSessionIdResolver resolver = new CookieWebSessionIdResolver();
resolver.addCookieInitializer(builder -> builder.domain("example.com"));
manager.setSessionIdResolver(resolver);
return manager;
}
2. As the attacker, from a compromised sibling subdomain (for example app.example.com, compromised via cross-site scripting), write a session cookie for the parent domain into the victim's browser with a known, attacker-chosen session ID value:
document.cookie = "SESSION=attacker-known-session-id; domain=example.com; path=/";3. As the victim, browse to the legitimate WebFlux application on another subdomain and authenticate normally. The browser sends the attacker-seeded SESSION cookie because it is scoped to the shared parent domain.
4. Observe that, on a vulnerable version, the authenticated session remains bound to the attacker-known session ID rather than a fresh server-generated ID.
5. As the attacker, send a request to the application carrying the same known session ID. The request is admitted into the victim's now-authenticated session, granting the attacker the victim's authenticated authority.
6. After upgrading to a fixed version (7.0.8, 6.2.19, or a HeroDevs NES build), repeat steps 3 through 5. The authenticated session is established under a fresh server-generated ID, the attacker-known ID no longer maps to the authenticated session, and the replay in step 5 fails.
Mitigation
Only recent versions of Spring Framework receive community support and updates. The 5.3.x and 6.1.x lines are End-of-Life for open source and have no publicly available OSS fixes 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 OSS fix ships in Spring Framework 7.0.8 (7.0.x line) and 6.2.19 (6.2.x line).
- Leverage a commercial support partner like HeroDevs for post-EOL security support through Never-Ending Support (NES) for Spring Framework.
Credits
- This vulnerability was discovered internally by the Spring Security team.