What are common WebSocket security vulnerabilities and how do you mitigate them?
Learn common WebSocket security risks like CSWSH and how to mitigate them with origin validation, token auth, TLS, and rate limiting.
Expected Interview Answer
Common WebSocket vulnerabilities include Cross-Site WebSocket Hijacking (CSWSH), missing origin validation, unencrypted ws:// traffic, injection through unvalidated messages, and denial-of-service from unbounded connections or oversized frames. You mitigate them with strict origin checks, token-based authentication, TLS (wss://), input validation, and connection rate limiting.
Because the WebSocket handshake is an HTTP upgrade that automatically sends cookies but is not protected by the same-origin policy, an attacker page can open a socket to your server using the victim's cookies — this is CSWSH, the WebSocket cousin of CSRF. Defenses layer up: validate the Origin header server-side, authenticate with a short-lived token in the connection rather than relying on ambient cookies, force wss:// so traffic is encrypted, sanitize every inbound message before acting on it, and cap connections, message size, and message rate per client to blunt resource-exhaustion attacks.
- Prevents Cross-Site WebSocket Hijacking
- Blocks eavesdropping via encrypted wss://
- Stops injection from malicious payloads
- Limits denial-of-service from connection floods
- Ensures only authenticated clients connect
AI Mentor Explanation
Think of the boundary rope and the third umpire as your security layers. Anyone can bowl a delivery, but the umpire checks the front foot for a no-ball before it counts — that is origin validation rejecting a suspicious handshake. TLS is the sealed match ball nobody can tamper with mid-over, and a rate limit is the over count that stops one bowler from monopolising the game and exhausting the pitch.
Step-by-Step Explanation
Step 1
Validate the Origin header
On the upgrade request, compare the Origin header against an allowlist and reject any handshake from an untrusted site.
Step 2
Authenticate the connection
Require a short-lived token (passed in the subprotocol or an initial auth message) instead of relying on ambient cookies to defeat CSWSH.
Step 3
Enforce TLS with wss://
Serve only over wss:// so the handshake and all frames are encrypted, preventing eavesdropping and man-in-the-middle tampering.
Step 4
Validate and sanitize messages
Treat every inbound frame as untrusted input, validate its schema, and escape data before storing or echoing it to other clients.
Step 5
Rate limit and cap resources
Limit connections per IP, message rate, and maximum frame size to prevent denial-of-service and memory exhaustion.
What Interviewer Expects
- Understanding that same-origin policy does not protect the WebSocket handshake
- Ability to explain CSWSH and its relationship to CSRF
- Knowledge of origin validation and token-based authentication
- Awareness of TLS (wss://) and message-level input validation
- Practical DoS mitigations like rate limiting and frame-size caps
Common Mistakes
- Assuming CORS protects WebSockets the way it protects fetch
- Relying only on cookies for authentication, leaving CSWSH open
- Trusting the Origin header without a server-side allowlist
- Using unencrypted ws:// in production
- Never limiting connection count or message size, inviting DoS
Best Answer (HR Friendly)
“WebSockets can be attacked by malicious websites hijacking a logged-in user's connection, by eavesdroppers on unencrypted traffic, or by floods that overload the server. You defend against this by checking who is connecting, using a login token, encrypting the traffic, and limiting how much any one client can do.”
Code Example
wss.on('connection', (socket, req) => {
const origin = req.headers.origin
const ALLOWED = ['https://app.example.com']
if (!ALLOWED.includes(origin)) {
socket.close(1008, 'origin not allowed')
return
}
const token = new URL(req.url, 'https://x').searchParams.get('token')
const user = verifyJwt(token) // throws on invalid/expired
if (!user) {
socket.close(1008, 'unauthorized')
return
}
socket.on('message', (raw) => {
if (raw.length > 8192) return socket.close(1009, 'message too big')
const msg = safeParse(raw) // validate schema before acting
if (!msg) return
handle(user, msg)
})
})Follow-up Questions
- What exactly is Cross-Site WebSocket Hijacking and why does CORS not stop it?
- Why is a token in the connection safer than relying on cookies?
- How would you rate-limit WebSocket messages per client?
- How do you rotate or expire tokens for long-lived connections?
- What headers or checks defend against handshake spoofing?
MCQ Practice
1. Cross-Site WebSocket Hijacking is possible mainly because...
The handshake sends cookies automatically and is not blocked by same-origin policy, so a malicious page can open a socket with the victim's credentials.
2. Which is the strongest defense against CSWSH?
Combining server-side origin validation with a non-cookie token removes the ambient-credential weakness that CSWSH exploits.
3. Capping message size and connection rate primarily prevents...
Limiting frame size, message rate, and connection count blunts resource-exhaustion and denial-of-service attacks.
Flash Cards
What is CSWSH? — Cross-Site WebSocket Hijacking — a malicious page opens a socket to your server using the victim's ambient cookies, like CSRF for WebSockets.
Why doesn't CORS protect WebSockets? — The handshake is an HTTP upgrade not covered by the same-origin policy, so you must validate the Origin header yourself.
ws:// vs wss:// — wss:// runs over TLS and encrypts the handshake and all frames; ws:// is plaintext and unsafe for production.
Best auth for sockets? — A short-lived token passed in the connection, verified server-side, rather than relying on cookies alone.
Continue Learning
Related Interview Questions
How do you handle CORS and origin validation for WebSockets?
medium
How does WebSocket message fragmentation work, and why can a control frame appear in the middle of a message?
hard
Should a WebSocket be authenticated during the HTTP handshake or with a first application message, and what are the trade-offs?
hard
Your WebSocket fleet cannot recover after an outage because every client reconnects at once. What do you do on the server?
hard