Configuration & Environment
The server is reachable on a public interface over plain HTTP, or with TLS configuration that accepts downgrade, giving an on-path attacker full read/write on tool calls.
A server that binds to `0.0.0.0` or an internet-routable IP with TLS disabled, or with `NODE_TLS_REJECT_UNAUTHORIZED=0`, or with a self-signed certificate the client was configured to blindly accept. Anyone on the network path can read the tool arguments (which often contain tokens or private data) and modify tool results.
Development defaults matter. An MCP server that worked on `localhost` is often deployed with the same `app.listen(3000)` to a public host. Because most transport is JSON over HTTP/SSE, there is no built-in confidentiality at that point.
import http from "node:http"; |
// Plain HTTP on a public interface |
const server = http.createServer(handler); |
server.listen(3000, "0.0.0.0"); |
import https from "node:https"; |
import fs from "node:fs"; |
const server = https.createServer( |
{ |
key: fs.readFileSync("/etc/ssl/private/key.pem"), |
cert: fs.readFileSync("/etc/ssl/certs/cert.pem"), |
minVersion: "TLSv1.3", |
}, |
handler, |
); |
server.listen(3000, "127.0.0.1"); // only reachable via reverse proxy |
We flag HTTP listeners without TLS when the bind address is not loopback, and any use of `NODE_TLS_REJECT_UNAUTHORIZED=0`, `verify=False`, or equivalent TLS-disabling flags.
See the full threat catalog for every documented detection.
MCPSafe runs this check — and every other rule in the catalog — on any MCP server you paste in.
Scan now