Security Concern
The rejoin_session handler in server.ts accepts any WebSocket client that knows the 6-character hex session ID. There is no verification that the reconnecting client is the same entity as the original disconnected peer.
Risk
- The session ID is derived from 3 random bytes (24 bits of entropy, ~16.7 million possibilities)
- An attacker who guesses or intercepts a session ID could send
rejoin_session and claim the tutor's grace-period slot
- This would allow hijacking the payment stream (receiving Cashu tokens intended for the legitimate tutor)
- Brute-force is feasible if sessions are long-lived
Suggested Fix
Include a high-entropy reconnect secret (e.g., 32-byte random token) in the session_created and session_rejoined responses:
- Server generates a random reconnect token per peer when they join
- Token is sent to the client in the
session_created / session_rejoined response
- Client stores the token and presents it in subsequent
rejoin_session messages
- Server validates the token before granting the grace-period slot
- Reject the rejoin if the token does not match
This does not require a full auth system — just a shared secret per session that proves the client was the original participant.
Security Concern
The
rejoin_sessionhandler inserver.tsaccepts any WebSocket client that knows the 6-character hex session ID. There is no verification that the reconnecting client is the same entity as the original disconnected peer.Risk
rejoin_sessionand claim the tutor's grace-period slotSuggested Fix
Include a high-entropy reconnect secret (e.g., 32-byte random token) in the
session_createdandsession_rejoinedresponses:session_created/session_rejoinedresponserejoin_sessionmessagesThis does not require a full auth system — just a shared secret per session that proves the client was the original participant.