Skip to content
← All posts
API security

Why WAFs Miss WebSocket Attacks, and How to Detect Them

Many WAFs stop reading at the WebSocket handshake. See the attacks that slip past, how to detect them in live frames, and a six-point test checklist.

Most WAFs inspect HTTP requests one at a time. A WebSocket connection is one HTTP request, the upgrade handshake, followed by a long-lived stream of frames. Once the handshake is accepted, many WAFs stop reading. Hijacking, injection and frame abuse then travel inside the connection, where only a tool that reads every frame can detect them.

If your platform has a chat feature, a real-time dashboard, a trading interface, a live order tracker or a collaborative document editor, you are almost certainly running WebSocket connections in production. If a traditional web application firewall is your main control for them, you have a blind spot.

This article walks through the four classes of WebSocket attack that bypass conventional security tooling, why they bypass it, what detection looks like when it works, and a six-point checklist for testing your own endpoints.

WebSocket is a protocol your WAF was not designed to read

A WAF inspects HTTP requests one at a time. Each request is a self-contained event with headers, a method, a path and a body. The WAF reads it, applies pattern rules, and lets it through or blocks it.

WebSocket breaks every assumption in that model.

A WebSocket connection begins with a single HTTP request, the upgrade handshake, and then becomes a long-lived, bidirectional, framed channel defined in RFC 6455. After that handshake, a filter that works request by request has nothing left to inspect. Hundreds or thousands of messages flow in both directions over the same connection. It cannot read message bodies, see frame headers or tell you what is being sent or received.

This is not a configuration issue. It follows from how request-based filters were built. Where frame inspection exists, it is often partial, or it buffers whole messages in a way that hurts real-time use.

The result: a significant share of your application’s runtime traffic is invisible to your security stack.

The four attack classes that exploit this blind spot

1. Cross-site WebSocket hijacking (CSWSH)

Cross-site WebSocket hijacking is the WebSocket equivalent of CSRF, and it is more dangerous because the attack window stays open for the entire session.

The attack works as follows. A user logs into your application and a WebSocket connection is established, authenticated by cookies. Later, the user visits a malicious page in another tab. That page silently opens a WebSocket connection back to your application using the JavaScript WebSocket API. Because the browser automatically sends authentication cookies with the WebSocket handshake, the new connection is authenticated as the user. The attacker now has a live, bidirectional channel into your application, acting as the victim.

What makes CSWSH particularly insidious is that the malicious page can keep the hijacked connection open and silently exfiltrate data, send commands or change state for as long as the tab stays open. There is no warning to the user, no interaction required, and no log entry that separates the hijacked connection from a legitimate one, unless you validate the origin.

2. Injection attacks inside WebSocket messages

WebSocket messages typically carry JSON payloads. Those payloads end up in the same backend code paths that handle HTTP request bodies, sometimes literally the same parsing functions. So every injection vulnerability in your REST API also exists in your WebSocket layer, except that nothing is inspecting the traffic.

SQL injection inside a WebSocket message looks identical to SQL injection inside an HTTP body. The attacker sends {"productId": "1' OR 1=1--"} over the open channel. Your backend parses the JSON, hands the value to a query builder, and the database executes the injected SQL. The WAF that would have blocked this at the HTTP layer never sees the message.

The same applies to NoSQL injection, command injection in shell-backed handlers, LDAP injection, XML and XPath injection, and template injection. Each is well understood in HTTP. None is inspected in WebSocket flows by default. Testers who replay their HTTP injection payloads over WebSocket regularly find handlers that never received the same validation.

3. Frame anomalies and fragmentation abuse

The WebSocket protocol allows a message to be split across multiple frames. A single logical message can be sent as a sequence of fragmented frames with continuation opcodes. This is legitimate behaviour, useful for streaming large payloads, but it is also a vector for evasion and resource exhaustion.

An attacker can send a message split across thousands of one-byte fragments. Each fragment is technically valid, but the cumulative effect forces your server to hold reassembly state for as long as the attacker likes. Multiplied across many connections, this is a low-bandwidth denial of service that slips past traditional rate limiting, because each fragment is small and individually harmless.

Other frame-level anomalies include unmasked frames from clients (forbidden by the specification but accepted by some servers), reserved bits set in the frame header (used by some extensions, but often the fingerprint of a malformed or malicious client), and oversized control frames (control frames are limited to 125 bytes; longer ones may exploit server parser bugs).

These are protocol-layer attacks. They do not look like application traffic. They look like normal, if slightly unusual, protocol behaviour. Application-layer logging will not catch them. Network firewalls do not understand the WebSocket frame format. You need wire-level visibility to see them.

4. Authentication and session weaknesses

WebSocket authentication is almost always handled at the handshake. The server validates the cookie or token, accepts the upgrade, and the connection then runs for thirty minutes, two hours, or until the user closes the tab, with no further authentication checks.

This creates two problems.

First, if a session token is compromised mid-session, through XSS, malware on the user’s machine or token theft from local storage, the attacker can ride the existing WebSocket connection until it disconnects. There is no per-message authentication to revoke.

Second, many WebSocket implementations accept tokens in URL query parameters during the handshake (wss://example.com/ws?token=abc123). Tokens in URLs end up in browser history, referrer headers, server access logs and proxy logs. Anyone with access to any of those gets the token.

Best practice is to authenticate with custom headers or a post-handshake authentication frame, and to validate and rotate tokens periodically within the session. In practice, many deployments trust whatever the initial handshake authenticated for the full lifetime of the connection.

How do you prevent cross-site WebSocket hijacking?

Treat the handshake as the security decision it is. Accept upgrades only from origins on an explicit allowlist, require a token that a third-party page cannot read, and never rely on the browser’s cookies alone to authenticate the connection. The defence is to check the origin on every handshake.

In practice, that means four controls:

  • Validate Origin on the server, every time. Compare it with an explicit allowlist. Avoid wildcards and substring matches, which are easy to get wrong. The OWASP WebSocket Security Cheat Sheet recommends the same.
  • Carry an anti-CSRF token into the session. Send it in the handshake or the opening message, separate from the session cookie, and close the connection if it is missing.
  • Set SameSite on session cookies. It reduces the risk, but sibling subdomains count as the same site, so it does not replace the origin check.
  • Re-check authorisation inside the session. A hijacked connection can only do what the server allows each message to do.

What detection actually requires

The common thread across these four attack classes is that they happen inside WebSocket frames after the handshake, exactly where request-based filters cannot see. Any detection approach that depends on HTTP-layer inspection misses all of them.

Effective detection requires three capabilities working together.

Wire-level visibility. Whatever sees the traffic must read WebSocket frames as they pass, not only the handshake. At Cyron, iris, the eBPF kernel agent, runs on the Linux host and copies REST, WebSocket, gRPC and Socket.IO traffic at the kernel, including every frame on every WebSocket connection, without sitting in the request path.

Protocol-aware parsing. Reading bytes is not enough. The detection layer must understand the WebSocket framing format, fragmentation and reassembly, masking rules, control versus data frames, and the JSON or binary payload inside each message. Cyron’s WebSocket analysis reads the wire-level features of every frame: opcode patterns, frame structure, fragmentation behaviour and message timing.

Behavioural baselining. Static rules such as “block messages containing the string SELECT” generate false positives and miss new attacks. Behavioural intelligence learns what normal looks like for each endpoint and watches whole sessions. Cyron runs per-endpoint baselines and 13 session-level rules, on Essential and above, including WebSocket subscription abuse, WebSocket replay across sessions and cross-protocol escalation.

Five API protocols, each read in its own format

Many security tools stop reading at the handshake. Cyron reads every WebSocket frame, gRPC message and event stream.

Cyron API Security covers five API protocols: REST and HTTP, WebSocket, gRPC, Server-Sent Events and Socket.IO. Socket.IO is analysed as a WebSocket transport, with event names. Server-Sent Events are analysed by the streaming engine. Across them, 31 real-time detectors for streaming and RPC APIs are grouped in seven families. Five of them matter most for WebSocket:

Detector familyWhat it catches on WebSocket
Injection inside messagesSQL injection, cross-site scripting, command injection, path traversal, Log4Shell and NoSQL injection inside a frame or message
Cross-site WebSocket hijackingMissing origin, mismatched origin
Floods and denial of serviceMessage floods, tiny-frame floods, sequence jumps
AuthenticationCredentials over unencrypted WebSocket, missing credentials
Header and metadata injectionInjection in upgrade headers

The other two families, gRPC wire level and Protobuf structure, cover gRPC.

A six-point WebSocket security test checklist

Run these tests against staging, or against production with permission. Each takes minutes with a scriptable WebSocket client or an intercepting proxy, and together they cover the core of a WebSocket penetration test.

  1. Origin. Replay the handshake with a foreign Origin header, then with none. The server should refuse both before the upgrade completes.
  2. Authentication. Open connections with no credentials, with an expired token and with a token in the query string. Each should fail, and no token should appear in your access logs.
  3. Injection. Send your HTTP injection payloads (SQL, NoSQL, command, path traversal) inside messages. The handler should reject them exactly as the matching REST endpoint does.
  4. Authorisation per message. Connected as user A, send messages that name user B’s objects or call admin actions. The server should check every message, not only the handshake.
  5. Limits. Send an oversized message, a message split into many tiny fragments, and a burst of messages. The server should enforce size, fragment and rate limits, and close the connection.
  6. Session end. Log out or revoke the token, then keep sending on the open connection. The server should close it promptly.

Anything that fails goes on the fix list below.

A practical hardening checklist for your team

If you run WebSocket in production today, these controls close most of the common gaps:

  • Enforce strict Origin header validation on every WebSocket handshake. Reject any handshake from an origin not on your explicit allowlist.
  • Require an anti-CSRF token in the handshake or first message, separate from the session cookie.
  • Authenticate every message inside the WebSocket connection, not just the handshake. Re-validate tokens periodically within the session.
  • Never accept tokens in URL query parameters. Use custom headers or post-handshake authentication frames.
  • Apply input validation and parameterised queries to WebSocket message payloads exactly as you do to HTTP bodies. The same backend code paths need the same defences.
  • Set explicit limits on message size, fragments per message and connection lifetime. Disconnect connections that exceed them.
  • Log every WebSocket connection with its origin, authenticated user, message count and bytes transferred. These logs make breach investigation possible.
  • Add a wire-level detection layer that reads frames inside the connection. Without it, every control above is enforced only by trust in your own code.

What this looks like in production

When iris runs on a host carrying WebSocket traffic, it recognises WebSocket upgrades in the kernel, follows the resulting connection and copies every frame to Cyron’s analysis. The detectors read each frame, and behavioural intelligence compares the session with its endpoint’s baseline. When a detector fires, Cyron raises an incident with the connection, the frame and its direction, and sends it to your SIEM as a signed, OCSF-aligned event.

The analysis runs out of band. Cyron analyses a copy of your traffic: no added latency, nothing in your request path, no code changes. Your WebSocket traffic carries on at full speed because nothing waits for a verdict.

Cyron’s streaming and RPC protection arrived in the Cyron March 2026 release, and the WebSocket detection walkthrough is on the Cyron YouTube channel.

Try it on your own APIs

Cyron’s free plan analyses five requests a minute on every protocol, with no card and no time limit. Point it at a test API that speaks WebSocket, run the six tests above, and see what the frames reveal.

If your APIs carry real-time traffic right now and nothing reads it at the wire level, that is the gap Cyron API Security was built for.

Start free

Updated 1 October 2026: new title, an answer on preventing cross-site WebSocket hijacking, a six-point test checklist and the five API protocols Cyron reads; product details brought up to date.