fix: validate Origin header on WebSocket upgrade to prevent cross-site WebSocket hijacking#210
Merged
buttercannfly merged 1 commit intoAIPexStudio:mainfrom Apr 3, 2026
Conversation
The MCP daemon WebSocket server accepts connections on all three endpoints (/bridge, /cli, /extension) without checking the Origin header. This allows a malicious web page to open a WebSocket to ws://127.0.0.1:9223/bridge and send tool calls that execute browser automation (navigate, click, read page content, take screenshots, access bookmarks/history). Add Origin header validation in the HTTP upgrade handler: - Allow connections with no Origin (Node.js clients: bridge.ts, cli.ts) - Allow chrome-extension:// and moz-extension:// origins - Reject all http:// and https:// origins with 403 Forbidden This prevents cross-site WebSocket hijacking (CSWSH) where JavaScript on an attacker-controlled page connects to the local daemon. CWE-319
Collaborator
|
Thanks @sebastiondev , really helpful commit |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Vulnerability Summary
Type: Cross-Site WebSocket Hijacking (CSWSH)
CWE: CWE-346: Origin Validation Error
Severity: High
File:
mcp-bridge/src/daemon.tsData Flow
The MCP daemon starts an HTTP server on
127.0.0.1:9223and upgrades connections to WebSocket on three paths (/extension,/bridge,/cli). All three paths go through a singlehttpServer.on("upgrade", ...)handler. The handler does not validate theOriginheader before completing the WebSocket handshake.Because the server is bound to
127.0.0.1, it is reachable from any JavaScript running in the user's browser. Browsers always attach anOriginheader on WebSocket connections initiated from web pages, and JavaScript cannot spoof this header. Without origin validation, any malicious web page can establish a WebSocket connection to the daemon and invoke the full AIPex tool suite.Exploit Scenario
A user with the AIPex daemon running visits a malicious (or ad-compromised) web page. The page connects to
ws://127.0.0.1:9223/bridgeand gains access to ~30+ MCP tools including:create_new_tab— open phishing pagescapture_screenshot— exfiltrate visual datadownload_text_as_markdown— exfiltrate page contentexecute_skill_script— run arbitrary skill scriptscomputer— simulate mouse/keyboard inputPreconditions (all highly realistic for any AIPex user)
Fix Description
1 file changed, 39 insertions, purely additive — no existing behavior modified.
The fix adds an
isOriginAllowed()function and an origin check at the single chokepoint — thehttpServer.on("upgrade")handler, which is the sole entry point for all three WebSocket paths.Allowed origins:
undefined(no header)bridge.ts,cli.ts,aipex-cli)wslibrary does not send Originchrome-extension://...moz-extension://...Rejected origins:
http://.../https://...Rejected connections receive
HTTP/1.1 403 Forbiddenand the socket is destroyed immediately — before the WebSocket handshake completes.Rationale
Originon WebSocket connections from web pages, and JavaScript cannot forge it. This makes origin checking a reliable defense.Test Results
14 tests were designed and validated covering:
Disprove Analysis
We systematically attempted to disprove or downgrade this finding:
Could authentication protect against this?
No.
grepfor auth-related patterns returned zero results indaemon.ts. All WebSocket endpoints are completely unauthenticated.Does localhost binding mitigate this?
Partially. It prevents remote network access, but CSWSH is a browser-based attack that originates from
127.0.0.1(the browser process). Localhost binding does not protect against it.Are there other mitigations?
None found. No CORS headers, no token-based validation, no input validation, no rate limiting.
Could there be bypass paths around the fix?
No. All three
WebSocketServerinstances (extensionWss,bridgeWss,cliWss) use{ noServer: true }, meaning the singleupgradehandler is the sole entry point. The/healthHTTP endpoint only returns status info and is CORS-blocked by browsers from cross-origin reads.Is this a known issue?
No prior security issues in the repository's issue tracker. No SECURITY.md found.
Prior art
CSWSH against localhost WebSocket servers is a well-documented attack class:
wslibrary documentation itself recommends origin validation when using{ noServer: true }CWE Classification Note
The initial finding was tagged CWE-319 (Cleartext Transmission). CWE-346 (Origin Validation Error) is a more precise classification for CSWSH. The vulnerability and fix remain the same regardless.
Verdict
CONFIRMED VALID — High confidence. The fix is clean (39 lines), correct (single chokepoint, no bypasses), purely additive, and addresses a real, exploitable vulnerability with high impact. No existing tests or functionality are affected.
Thank you for your time reviewing this. Happy to discuss or adjust anything.