Problem
The web server (both the prod backend clients/web/server/web-server-config.ts and the dev Vite server clients/web/vite.config.ts) passes the HOST env var straight through to its bind call with no validation. Setting HOST=0.0.0.0 (or ::, or empty) binds every network interface, exposing the Inspector's backend — which can spawn local processes and connect to MCP servers on the user's behalf — to the entire local network. That is precisely the surface DNS-rebinding attacks target.
The project's stated intent (specification/v2_scope.md: "Bind to localhost by default … never 0.0.0.0") was only a design note; nothing enforced it.
Proposal
Enshrine the localhost-only default in code, via a single shared guard used by both bind points:
- Refuse an all-interfaces host (
0.0.0.0 / :: / empty) by default, exiting with an actionable error.
- Allow it only when
DANGEROUSLY_BIND_ALL_INTERFACES=true is explicitly set (same DANGEROUSLY_* opt-in pattern as DANGEROUSLY_OMIT_AUTH).
- The published Docker image is the sanctioned exception (a container must bind
0.0.0.0 to be reachable through -p), so its Dockerfile sets the flag.
Related fix folded into the same PR
Investigation started from a real bug: connecting to a plain stdio server (everything-server) failed with Remote connect failed (403): Invalid origin … DNS rebinding. Root cause: the dev server binds IPv6 loopback [::1], the browser lands on http://[::1]:6274, but the default allowedOrigins was the single literal string http://localhost:6274, so the origin guard 403'd the connect. The same PR expands the default loopback allowedOrigins to all three interchangeable forms (localhost, 127.0.0.1, [::1]) for the port.
Problem
The web server (both the prod backend
clients/web/server/web-server-config.tsand the dev Vite serverclients/web/vite.config.ts) passes theHOSTenv var straight through to its bind call with no validation. SettingHOST=0.0.0.0(or::, or empty) binds every network interface, exposing the Inspector's backend — which can spawn local processes and connect to MCP servers on the user's behalf — to the entire local network. That is precisely the surface DNS-rebinding attacks target.The project's stated intent (
specification/v2_scope.md: "Bind to localhost by default … never 0.0.0.0") was only a design note; nothing enforced it.Proposal
Enshrine the localhost-only default in code, via a single shared guard used by both bind points:
0.0.0.0/::/ empty) by default, exiting with an actionable error.DANGEROUSLY_BIND_ALL_INTERFACES=trueis explicitly set (sameDANGEROUSLY_*opt-in pattern asDANGEROUSLY_OMIT_AUTH).0.0.0.0to be reachable through-p), so itsDockerfilesets the flag.Related fix folded into the same PR
Investigation started from a real bug: connecting to a plain stdio server (
everything-server) failed withRemote connect failed (403): Invalid origin … DNS rebinding. Root cause: the dev server binds IPv6 loopback[::1], the browser lands onhttp://[::1]:6274, but the defaultallowedOriginswas the single literal stringhttp://localhost:6274, so the origin guard 403'd the connect. The same PR expands the default loopbackallowedOriginsto all three interchangeable forms (localhost,127.0.0.1,[::1]) for the port.