KamoCRM

Guard STOMP SUBSCRIBE to a session's live messages and WebRTC signaling

FixMediaService
Shipped
September 23, 2026 at 11:14 AM UTC
Author
Kamo
Commit
d47b471

/topic/chat/session/{guid} and /topic/webrtc/session/{guid} were not guarded at all: any authenticated socket could SUBSCRIBE to another session's live chat messages or WebRTC offer/answer/ICE traffic purely by knowing (or guessing) its guid - the live twin of the transcript-read hole MediaController.canReadSession closed for HTTP (f7b2bd5). Client SEND to either was also open; no legitimate client ever sends to them (every real one only subscribes), so a forged SEND could inject a fake live message or signaling frame into a session the forger cannot even read. WebSocketConfig.preSend now guards SUBSCRIBE to both prefixes with SessionAccessGuard#canRead - the same rule MediaController's read gate uses, not a fourth copy of it - and **************** now refuses SEND to both outright, matching every other topic in that allowlist. canRead needed a second entry point: its existing signature asks an HttpServletRequest for the caller's rights (SUPPORT_TICKET's extra admission), and a STOMP frame has none - only what WebSocketAuthInterceptor stamped into the session at CONNECT (memberId/orgId/rights, read off the same *** session an HTTP request would have resolved). The new canRead(session, caller, List<String> rights) overload takes that shape directly; both overloads now delegate to one private implementation, so the actual rule is still written exactly once. A public chat visitor is not a Member at all - PublicChatWebSocketInterceptor stamps isPublicChat/sessionGuid instead, already resolved and verified against their session token at handshake. Their subscribe rule is a direct guid match against that, never SessionAccessGuard#canRead (which requires a Member and would refuse a caller who has none) - confirmed against kamo-internal, which only ever subscribes to these two topics and never sends to either. Covered by **************** (member admitted/refused by the guard, a public visitor admitted to their own session and refused a different one, unrelated topics untouched), new cases in SessionAccessGuardTest and StompDestinationAuthzTest for the rights-list overload and the new SEND refusal. Mutation-checked: dropping the new SUBSCRIBE check, breaking the rights-list overload's own rule, and (as a regression check) the pre-existing "unguarded" assertion this closes each turn a specific assertion red; all restored and rerun green.

All changes

Like what you see shipping?

All of it arrives in your workspace on its own. Start on the free plan and read this page again in a month.

Start Free ForeverView Pricing