Web Security

WebSocket Security: Vulnerabilities, Attacks, and Testing Guide

A complete technical guide to WebSocket security: cross-site WebSocket hijacking, WS downgrade attacks, message injection, origin validation bypasses, and how to test WebSocket endpoints safely.

Intermediate12 min·Nyxeara Security Research·2026-09-21·CWE-345
websocketweb-securityrealtime-securityws-hijackingapi-securitypentesting
Prerequisites
what-is-httpwhat-is-a-url

Short answer

WebSocket connections bypass the standard HTTP request-security model. Once established, a WebSocket is a persistent bidirectional tunnel that neither the browser nor the server re-authenticates. If the initial handshake is vulnerable to cross-site request forgery, an attacker can open a WebSocket connection as the victim and send or receive arbitrary messages.

The idea in one minute

A WebSocket is like a phone call between the browser and the server. The authentication happens when the call connects — you verify the caller's identity once. After that, every message you exchange over that call is trusted because you already checked who was on the line. The problem: what if an attacker causes the victim's phone to dial the server without the victim knowing? The attacker hides in the room, and every time the server asks "who is this?," the victim (who is still on the call) replies "it's me." The attacker listens to every response and whispers instructions into the victim's ear.

The technical mechanism: a page on evil.com opens a WebSocket to wss://target.com/chat. The browser automatically attaches target.com's cookies to the WebSocket upgrade handshake. If the server does not validate the Origin header, it accepts the connection as authenticated. Evil.com can now send and receive messages through the victim's session.

How WebSocket authentication works

WebSocket connections begin as HTTP requests — the "upgrade handshake":

GET /chat HTTP/1.1
Host: target.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: https://target.com
Cookie: session=abc123

The server responds with 101 Switching Protocols, and from that moment, the connection is a raw TCP tunnel with no further authentication. The server trusts that whoever was authenticated by the HTTP request remains the same entity for the life of the connection.

This trust model has a critical gap: the Cookie header is attached automatically by the browser. If the server only checks the cookie, any cross-origin page can open a WebSocket to the target and the victim's browser will attach the cookies. The server cannot distinguish between the legitimate page and the attacker's page unless it validates the Origin header.

Cross-Site WebSocket Hijacking

The most common and most dangerous WebSocket vulnerability. It is essentially CSRF for WebSocket connections:

  1. User is authenticated to target.com.
  2. User visits evil.com.
  3. evil.com executes: new WebSocket('wss://target.com/chat').
  4. Browser attaches target.com's cookies to the handshake.
  5. Server accepts the connection — it sees a valid session cookie.
  6. evil.com sends messages through the socket and reads responses.

The impact depends on what the WebSocket does. If it streams real-time notifications, the attacker reads every notification. If it accepts commands to transfer money, the attacker can initiate transfers. If it exposes internal service data, the attacker can enumerate the infrastructure.

Detection: Open a WebSocket to the target from a different origin (a local HTML file or a page on a different domain). If the connection succeeds without validating the Origin header, the server is vulnerable.

Origin validation bypasses

Servers that do check the Origin header often do it wrong:

  • String inclusion: if (origin.includes("target.com")) — bypassed with https://target.com.evil.com
  • Prefix match: if (origin.startsWith("https://target.com")) — bypassed with https://target.com.evil.com
  • Suffix match: if (origin.endsWith("target.com")) — bypassed with https://eviltarget.com
  • Null origin: Some servers accept Origin: null (sent by file:// pages, data URIs, or sandboxed iframes). An attacker can open a sandboxed iframe that sends Origin: null.

WebSocket message injection

Even when the connection is legitimate, the server may trust all incoming messages without authentication. In applications where a WebSocket handles state-changing operations, each message should independently authenticate. Common patterns:

Message from server: {"type": "auth_required", "token": "..."}
Client response: {"type": "auth", "token": "..."}

If the server sends an authentication challenge on connect but then trusts all subsequent messages from that connection, an XSS vulnerability on the page can intercept the auth token and send arbitrary messages through the real socket.

WSS downgrade to WS

Secure WebSocket (WSS) over TLS provides confidentiality and integrity. If the page loads over HTTPS but connects to an insecure WebSocket (ws:// instead of wss://), an attacker on the network can intercept and modify every message. This is mixed content for WebSockets.

Detection: Check the new WebSocket() URL in the page source. If it uses ws:// and the page is served over HTTPS, the connection is vulnerable to network-level interception.

Message format confusion

WebSocket messages can be text or binary. Security logic sometimes differs between the two formats. An API that sanitizes text messages but passes binary messages directly to a parser may have injection vulnerabilities that are only reachable through binary frames.

Verification: real vulnerability or false positive?

A WebSocket connection from a different origin that succeeds is a vulnerability if the connection provides access to authenticated data or state-changing operations. If the server sends a new authentication challenge over the WebSocket (a per-connection token), the CSRF risk is mitigated — but the token must be unpredictable and checked on every message. A static token is not a mitigation.

Real-world impact

In 2019, a cryptocurrency exchange had a WebSocket-based trading API with no Origin validation. An attacker who tricked a trader into visiting a malicious page could place orders through the trader's authenticated WebSocket connection. The vulnerability affected one of the top 10 exchanges by volume and could have been exploited with a single line of JavaScript.

Prevention checklist

  1. Validate the Origin header on every WebSocket upgrade handshake. Use an exact match against an allowlist — never substring matching.
  2. Never rely on cookies for WebSocket authentication without Origin validation. Use a per-connection token obtained from a REST API call and passed as the first WebSocket message.
  3. Enforce WSS-only. Reject plain ws:// connections in production.
  4. Apply per-message authentication for state-changing operations over the WebSocket.
  5. Rate-limit WebSocket connections per session to prevent resource exhaustion.
  6. Validate the format and length of every incoming message before processing it.
  7. Close connections that send invalid or unexpected messages.

Related vulnerabilities

  • CSRF — Cross-Site WebSocket Hijacking is CSRF applied to the WebSocket upgrade mechanism.
  • CORS — CORS protects XHR/fetch, not WebSockets. A misconfigured CORS policy does not imply a WebSocket vulnerability, and vice versa.
  • Origin validation bypasses — The same string-matching mistakes that break CORS also break WebSocket Origin checks.

Testing methodology (do this safely)

Open a WebSocket from a local HTML file to the target using new WebSocket('wss://target.com/path'). If the onopen handler fires, test whether the server validates the Origin header. Send a test message and check whether the response contains data you shouldn't have access to. Always test on your own applications or authorized bug bounty programs. For production targets, use read-only test connections and never send state-changing messages without explicit authorization.

Further reading

Nyxeara perspective

WebSocket connections in the Nyxeara relay system use a Flask-validated bearer token at connect time, not cookies. Origin validation is enforced server-side. The relay lifetime is capped at 15 minutes with a bounded frame queue to prevent resource exhaustion. The Nyxeara verification engine tests WebSocket endpoints for origin validation and WSS downgrade as part of the API security scan — a WebSocket without Origin validation is a high-severity CANDIDATE that triggers a cross-site hijacking verification playbook.

Published 2026-09-21 · Updated 2026-09-21