CVE-2026-41838
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 core container, data access, web, and messaging support for a large share of enterprise Java applications. Its spring-websocket module implements the server side of the Java WebSocket and STOMP-over-WebSocket programming models, and assigns every established WebSocket session a session id that the framework and applications use to identify and route that connection.
A medium-severity vulnerability (CVE-2026-41838) has been identified in the spring-websocket module. The shared id generator used to mint WebSocket session ids is AlternativeJdkIdGenerator, which seeds an ordinary java.util.Random once from SecureRandom and then draws every subsequent id from that non-cryptographic generator. Because java.util.Random is a 48-bit linear congruential generator, an attacker who observes a small number of session ids minted by a running server can recover the generator state and predict the ids that will be assigned to other sessions, including those of other users. In combination with inadequate authorization rules (for example, an application that treats the WebSocket session id as a secret or capability), a predictable id can enable session prediction or hijacking.
Per OWASP: session identifiers must be generated with a cryptographically secure source of randomness so that they cannot be guessed or predicted by an attacker, and identifiers that are predictable undermine any authorization decision that relies on them. Information Exposure of this kind arises when an identifier that is relied upon to be unguessable is in fact derived from a weak pseudo-random sequence, allowing an attacker to learn or infer values that were intended to be unpredictable.
The CVSS v3.1 base score for this vulnerability is 4.2 (Medium) with vector AV:N/AC:H/PR:L/UI:R/S:U/C:H/I:N/A:N. The attack vector is Network because WebSocket sessions are established remotely, attack complexity is High because the attacker must recover the generator state from observed ids and win a race to act on a predicted session, the privileges required are Low because a realistic abuser is an authenticated low-privilege participant who can mint their own sessions, and user interaction is Required. The impact is Confidentiality-only and High (predicting and acting on another user's session can expose that user's data); there is no integrity or availability impact in the rated vector.
This issue affects Spring Framework >=5.1.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-websocket
- Affected versions: >=5.1.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-websocket
- Package manager: Maven
- Fixed in:
- NES for Spring Framework 5.3.x, 6.1.x
- Spring Framework 6.2.19, 7.0.8 (OSS)
Vulnerability Info
The vulnerability is in AbstractWebSocketSession in the spring-websocket module, the base class for the framework's server-side WebSocket session adapters (for example StandardWebSocketSession and JettyWebSocketSession). All of those adapters obtain their session id from a single shared static idGenerator field declared on AbstractWebSocketSession. Pre-fix, that field is an AlternativeJdkIdGenerator:
import org.springframework.util.AlternativeJdkIdGenerator;
...
protected static final IdGenerator idGenerator = new AlternativeJdkIdGenerator();
AlternativeJdkIdGenerator was originally chosen as a faster alternative to generating a fresh UUID per id. Its implementation seeds a plain java.util.Random exactly once, from SecureRandom, and then produces every id from that Random:
public class AlternativeJdkIdGenerator implements IdGenerator {
private final Random random;
public AlternativeJdkIdGenerator() {
SecureRandom secureRandom = new SecureRandom();
byte[] seed = new byte[8];
secureRandom.nextBytes(seed);
this.random = new Random(new BigInteger(seed).longValue());
}
@Override
public UUID generateId() {
byte[] randomBytes = new byte[16];
this.random.nextBytes(randomBytes);
long mostSigBits = 0;
for (int i = 0; i < 8; i++) {
mostSigBits = (mostSigBits << 8) | (randomBytes[i] & 0xff);
}
long leastSigBits = 0;
for (int i = 8; i < 16; i++) {
leastSigBits = (leastSigBits << 8) | (randomBytes[i] & 0xff);
}
return new UUID(mostSigBits, leastSigBits);
}
}
The problem is that java.util.Random is a 48-bit linear congruential generator, not a cryptographic one. Its entire internal state is recoverable from a couple of observed outputs, after which every future output is determined. Because the WebSocket session id generator is a single shared static instance seeded once at class load, all session ids minted by a given server process come from one such recoverable sequence. An attacker who can observe a small number of ids (for example by opening their own WebSocket sessions) can therefore predict the ids assigned to other sessions on the same server. The only entropy protecting the sequence is the 8-byte (64-bit) initial seed, which does not help once outputs are observable.
The vulnerable generator was introduced together with framework-assigned WebSocket session ids, in 2018, and first shipped in Spring Framework 5.1.0. Before that, AbstractWebSocketSession had no id generator and StandardWebSocketSession returned the session id supplied by the underlying servlet or WebSocket container, so the predictable-id code path did not exist. The advisory's listed range starting at 5.3.x reflects Spring's currently-supported scope; Spring Framework 5.1.x and 5.2.x that contain this code path are affected as well, while 4.3.x and earlier are not.
Steps To Reproduce
1. Build a Spring application using the spring-websocket module on an affected version (for example 6.2.18) with a WebSocket handler registered, so that incoming connections are backed by StandardWebSocketSession (or another AbstractWebSocketSession subclass).
2. Open several WebSocket connections to the server and record the assigned session ids, available from WebSocketSession.getId() on the server side (and frequently surfaced to clients, for example in STOMP frames or application-level identifiers):
public class IdLoggingHandler extends TextWebSocketHandler {
@Override
public void afterConnectionEstablished(WebSocketSession session) {
System.out.println("session id = " + session.getId());
}
}
3. Observe that all ids minted by the server process come from a single java.util.Random sequence seeded once at class load. Recover the generator state from a small number of observed ids by reproducing the same computation that AlternativeJdkIdGenerator.generateId() performs over a java.util.Random:
// Given a few consecutive observed 16-byte id values from the server,
// a standard java.util.Random state-recovery (LCG inversion) yields the
// 48-bit internal state, after which random.nextBytes(new byte[16]) can be
// replayed to compute the UUIDs the server will assign to subsequent sessions.
Random predicted = reconstructRandomFromObservedIds(observedIds);
byte[] next = new byte[16];
predicted.nextBytes(next);
// 'next' reconstructs the most/least significant bits of the next session UUID
4. Confirm that the predicted next id matches the id the server actually assigns to the next session it creates. Where the application relies on the WebSocket session id as a secret or capability under inadequate authorization rules, the predicted id can then be used to target another user's session.
5. After upgrading to a fixed version (6.2.19, 7.0.8, or a HeroDevs NES build), repeat steps 2 through 4. Session ids are now produced by JdkIdGenerator via UUID.randomUUID(), draw from SecureRandom on every call, and cannot be predicted from previously observed ids.
Mitigation
Only recent versions of Spring Framework receive community (OSS) updates. The fix is publicly available only for the actively supported lines.
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 6.2.19 (6.2.x line) and 7.0.8 (7.0.x line).
- Where an upgrade is not immediately possible, review and harden authorization so that the WebSocket session id is never treated as a secret or capability; authorization decisions and per-session access control should not rely on the unguessability of the session id.
- Leverage a commercial support partner like HeroDevs for security support on end-of-life lines through Never-Ending Support (NES) for Spring Framework, which provides the fix for the 5.3.x and 6.1.x lines that have no public OSS fix.
Credits
- This issue was discovered internally by the Spring Framework team.