CVE-2025-41254: Spring Framework STOMP over WebSocket applications may allow attackers to send unauthorized messages
4.3
Basic Information
Technical Details
| Package Name | Ecosystem | Vulnerable Versions | First Patched Version | 
|---|---|---|---|
| org.springframework:spring-websocket | maven | >= 6.2.0, < 6.2.12 | 6.2.12 | 
| org.springframework:spring-websocket | maven | >= 6.1.0, <= 6.1.21 | |
| org.springframework:spring-websocket | maven | >= 6.0.0, <= 6.0.23 | |
| org.springframework:spring-websocket | maven | <= 5.3.39 | 
Vulnerability Intelligence Miggo AI
Miggo AI
 Root Cause Analysis
Root Cause Analysis
The vulnerability, CVE-2025-41254, allows an attacker to send unauthorized STOMP messages over a WebSocket connection. The root cause lies in a state management flaw within the StompSubProtocolHandler class in spring-websocket.
My analysis of the patch between the vulnerable version (6.2.11) and the fixed version (6.2.12) pinpoints the commit c88bfc54c9256e3c07511aa303be2b136c03e0e2, which refactors this state management.
In the vulnerable version, the handler used separate maps to track message channels and authenticated STOMP users (stompAuthentications). A user was associated with a session via a callback after a CONNECT message was sent for processing. This created a race condition. An attacker could send a WebSocket message containing multiple STOMP frames, such as a SEND or SUBSCRIBE frame before the initial CONNECT frame was fully processed and authenticated.
The handleMessageFromClient function would process these frames sequentially. Before the STOMP user was established in the stompAuthentications map, the getUser function would fall back to using the principal from the underlying WebSocket session. This could allow messages to be processed with incorrect permissions, either those of an anonymous user or a less-privileged user associated with the WebSocket handshake, bypassing the intended STOMP-level authorization.
The fix introduces a SessionInfo class that atomically holds all session-related state, including the message channel and the user principal. This SessionInfo object is created and stored in a map only upon receiving a CONNECT frame. For any subsequent frames, the code now asserts that a session must already exist. This enforces a strict protocol flow, ensuring no STOMP messages are processed before a session is properly established and authenticated, thus closing the security bypass.
The primary vulnerable function is handleMessageFromClient as it's the entry point for processing malicious STOMP messages. The getUser function is also a key part of the vulnerable logic.
Vulnerable functions
org.springframework.web.socket.messaging.StompSubProtocolHandler.handleMessageFromClientspring-websocket/src/main/java/org/springframework/web/socket/messaging/StompSubProtocolHandler.java
org.springframework.web.socket.messaging.StompSubProtocolHandler.getUserspring-websocket/src/main/java/org/springframework/web/socket/messaging/StompSubProtocolHandler.java