Skip to content

fix(security): bind the extension control channel to loopback and gate its handshake#53

Merged
aaronjmars merged 1 commit into
mainfrom
security/ws-loopback-bind
Jul 20, 2026
Merged

fix(security): bind the extension control channel to loopback and gate its handshake#53
aaronjmars merged 1 commit into
mainfrom
security/ws-loopback-bind

Conversation

@aaronjmars

Copy link
Copy Markdown
Collaborator

fix(security): bind the extension control channel to loopback and gate its handshake

The WebSocket server was created as new WebSocket.Server({ port: WS_PORT }).
With no host, Node listens on all interfaces, so the browser-automation
control channel was reachable from the LAN. The connection handler hands
chromeExtensionSocket to whoever connects last, closing the previous socket,
so any reachable peer could evict the real extension, receive every automation
command the MCP server issues, and return fabricated results to the model.

Two changes:

  • Bind to 127.0.0.1. The extension connects to ws://localhost:5555 from the
    same machine and the optional ngrok tunnel forwards the HTTP port only, so
    nothing legitimate needs this off-host.
  • Add a verifyClient gate. Loopback alone is not sufficient: a web page the
    user visits can also reach 127.0.0.1. Browsers send Origin on a cross-origin
    WebSocket handshake, so page-initiated connections are rejected while
    extension-scheme origins and local non-browser clients are allowed.

Verified against a running server:

bind address 127.0.0.1:5711 (was *:5711)
loopback + chrome-extension:// ACCEPTED
loopback + no origin ACCEPTED
loopback + https://evil.example REJECTED 403
LAN 10.x.x.x ECONNREFUSED

Not addressed here: the HTTP/SSE server still listens on all interfaces with
Access-Control-Allow-Origin: *. That one needs a separate decision because
remote MCP clients and the tunnel path may depend on it.

Co-Authored-By: Claude noreply@anthropic.com

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant