Safeguard
Application Security•

CWE-1385 Missing Origin Validation in WebSockets (CSWSH)

WebSockets skip the same-origin protections that guard ordinary requests. Without an Origin check, any web page can hijack a logged in user's socket.

Safeguard Security Team
5 min read

CWE-1385 is the weakness of using a WebSocket without properly verifying that the source of the communication is valid. The attack built on it is Cross-Site WebSocket Hijacking, and it threatens any app with a socket behind a login, including local developer tools and admin consoles.

How it happens

A WebSocket gives a client and server a long-lived, bidirectional, low latency channel. It can ride over ports 80 and 443 but is not limited to HTTP.

The important point from MITRE: WebSockets can make cross-origin requests that browser protections such as the Same Origin Policy and CORS do not restrict. Without explicit origin validation, that makes CSRF attacks more powerful. A malicious page can open a socket to your server from the victim's browser, and the browser attaches the victim's cookies to the handshake. If the server accepts the handshake, the attacker's page can then read and send messages as the user.

// Vulnerable: Node ws server accepts any origin
const WebSocket = require("ws");
const wss = new WebSocket.Server({ port: 8080 });

wss.on("connection", (ws, req) => {
  // session cookie is trusted, Origin header never checked
  ws.on("message", (msg) => handle(ws, req, msg));
});
// Safer: check Origin during the handshake
const WebSocket = require("ws");
const ALLOWED = new Set(["https://app.example.com"]);

const wss = new WebSocket.Server({
  port: 8080,
  verifyClient: (info) => ALLOWED.has(info.origin),
  maxPayload: 64 * 1024,
});

Compare origins by exact match, not by substring. The record shows what happens otherwise.

The record lists four CVEs:

  • CVE-2020-25095: the web console of a SIEM product does not check the Origin header, allowing Cross-Site WebSocket Hijacking.
  • CVE-2018-6651: a chain in which a gaming client tries to validate the Origin header but only uses a substring, so requests forced from an origin whose hostname contains the expected one allow hijacking.
  • CVE-2018-14730 and CVE-2018-14731: WebSocket servers that do not check the origin of requests let attackers steal a developer's code through connections to local addresses, one on a fixed port and one on a randomized port.

The last two matter because they show local services are not safe just because they listen on loopback. A web page in the developer's own browser can reach them.

What an attacker gains

MITRE says consequences vary with what the socket does. They can include reading and modifying application data, gaining privileges or assuming the user's identity, bypassing protection mechanisms, and causing a crash, across confidentiality, integrity, availability and access control.

How to find it

The record lists no detection methods. Practical checks:

  • Find every WebSocket endpoint and check whether the handshake handler reads the Origin header.
  • Open a page on a different origin (a local test page is enough) that connects to your socket. If the connection succeeds with the user's session, it is exposed.
  • Test the allow check with look alike origins, such as a hostname that contains yours as a substring.
  • Run a dynamic scan against the application. Check which socket libraries you use and whether known advisories apply, with the free scanner at gold.safeguard.sh/scan, which needs no login and covers up to 100 dependencies.

How to fix it

From the record:

  1. Verify the Origin header during the handshake, as a CORS-like restriction.
  2. Use a randomized CSRF token to verify requests.
  3. Use TLS, with wss rather than ws.
  4. Require user authentication before the connection is established. The Node ws library has a verifyClient function for this.
  5. Apply rate limiting, for example a leaky bucket, to reduce denial of service. Defense in depth.
  6. Limit payload size. The Node ws library has a maxPayload option. Defense in depth.
  7. Treat data as untrusted in both directions and sanitize it as you would for XSS or SQL injection.

Cookie settings also help: a SameSite attribute on session cookies reduces what a cross-site handshake carries, but it is not a replacement for an Origin check.

Try it yourself

See how a web app scan probes endpoints and reports weak handshakes.

Click through it at your own pace, or open it full screen.

Quick check

Why does CORS not protect a WebSocket? WebSockets can make cross-origin requests that are not restricted by the Same Origin Policy or CORS, so the server has to check the Origin itself.

Why is a substring check on Origin unsafe? An attacker can register a hostname that contains the expected name, and the check passes. Use exact matching.

Is a service on localhost safe from this? No. The record shows local WebSocket servers whose data was stolen by web pages open in the developer's browser.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.