RoastMyOpsec

Vulnerabilities

WebSockets vs CORS for Browser APIs

June 15, 2026

WebSockets vs CORS for browser APIs is two different browser gates. CORS decides whether fetch/XHR may read a cross-origin HTTP response. A WebSocket starts as HTTP Upgrade; after the handshake, frames are not CORS-checked. Access-Control-Allow-Origin on the REST API does not protect wss://. The server must verify Origin (and cookies or tokens) on the upgrade. Reflecting any Origin or skipping the check is the miss. RoastMyOpsec app mode sends a bounded untrusted Origin on HTTP and reads ACAO. It does not open WebSockets, does not send upgrade frames, and does not score missing Origin checks on wss.

The practical difference

fetch() to https://api.example/data is CORS. new WebSocket('wss://api.example/ws') is a handshake the page's origin is sent on. Same-site cookies may attach depending on SameSite. JSONP is a third gate — script tags — already retired in the JSONP vs CORS guide.

SameSite=None cookies on a WebSocket cookie-auth API are an embed decision. Prefer tokens in the handshake your app already uses for HTTP, not a second cookie policy.

How to choose a gate

Public read-only WS: still allowlist Origin so random sites cannot open a socket on your users' behalf if the socket is cookie-authenticated. Anonymous market-data sockets can allow more origins but should not trust the client as a user. Authenticated sockets: Origin allowlist plus a session or ticket. Do not copy CORS * onto the upgrade.

ChannelBrowser gateServer mustTakeaway
fetch / XHRCORSACAO allowlist; still auth the userSee wildcard vs allowlist
WebSocketNo CORS on framesCheck Origin; authenticate upgradeCORS headers do not apply
JSONPScript tagRetire itSee JSONP vs CORS
Same-origin WSSame origin as the pageStill authenticateOrigin check is easy to get right

What the roast can prove

HTTP ACAO and credentials behavior can surface. A 101 is not in the scan. Confirm Origin handling on your own upgrade path. Pair with CORS credentials vs wildcard if the socket uses cookies.

Common mistakes

The first mistake is tightening CORS and leaving the WebSocket Origin check as *.

The second mistake is cookie-auth sockets with SameSite=None for a widget you do not trust.

The third mistake is treating a roast ACAO pass as proof the socket is locked.

Free audit the URL you own

RoastMyOpsec is a defensive public-surface roast: headers, cookies, sensitive paths, and more — no exploit payloads. Start with the free audit, then open the vault if the blurred findings look expensive.

Free audit now

FAQ

Does CORS protect WebSockets?
No. Frames after upgrade are not CORS-gated. Check Origin and authenticate on the handshake.
Should every site Origin-check WebSockets?
If the socket is authenticated or user-specific, yes. Anonymous public streams still benefit from an allowlist.
Does RoastMyOpsec open WebSockets?
No. It does not send Upgrade or score wss Origin handling.

Sources

Related guides