21,000 MCP servers exposed on the internet: why authentication is "optional"
by detektd team

In a year, the Model Context Protocol (MCP) became the de facto standard for wiring tools into an AI assistant: a database, a Git repo, a CRM, a shell. An MCP server exposes tools; a client (Claude, Cursor, a homegrown agent) discovers and calls them. The protocol was designed to run locally first. It now runs, massively, on the internet.
In late April 2026, Censys identified 12,520 internet-reachable MCP services across 8,758 IP addresses; by early May, the count passed 21,000. On July 31, a study published on arXiv, "Exposed by Design", measured that fleet dynamically: 640 confirmed production servers, 414 audited, 68 reportable vulnerabilities. And above all, 91.8% of audited servers had no OAuth authentication in place.
of audited production MCP servers had no OAuth authentication (arXiv 2608.00150, July 2026)
How MCP works
Under the hood, MCP is JSON-RPC 2.0. A session starts with an initialize exchange, where client and server announce their protocol version and capabilities. The client then calls tools/list to get the list of tools, each described by a name, a natural-language description and a JSON schema for its arguments. Then tools/call to run one. The server can also expose "resources" (addressable data) and "prompts" (interaction templates).
{
"name": "query_customers",
"description": "Run a read query against the customers table",
"inputSchema": {
"type": "object",
"properties": { "sql": { "type": "string" } },
"required": ["sql"]
}
}The protocol defines two transports. The first, stdio, runs the server as a subprocess of the client: no network port, no possible exposure, and the specification asks clients to prefer it. The second, Streamable HTTP, turns the server into an independent HTTP service, with a single endpoint accepting POST and GET that can stream responses (Server-Sent Events). In March 2025 it replaced the older HTTP+SSE transport from version 2024-11-05, still present on many deployments.
"OPTIONAL"
MCP's authorization specification opens with a sentence that explains much of the numbers: authorization is OPTIONAL, in capitals, in the RFC sense. When implemented, it's solid: OAuth 2.1 with mandatory PKCE, authorization server discovery through protected resource metadata (RFC 9728), tokens bound to their audience through resource indicators (RFC 8707), and an explicit ban on passing a received token straight through to another API. But nothing forces anyone to implement it.
That choice makes sense for stdio, where the server inherits the local user's rights. It makes far less sense for an HTTP service. The HTTP transport's security section acknowledges as much: servers MUST validate the Origin header of every connection to prevent DNS rebinding attacks, SHOULD bind only to 127.0.0.1 when running locally, and SHOULD authenticate all connections.
How a local server ends up on the internet
The typical scenario is mundane. An MCP server starts locally, over stdio. To share it with the team, it's switched to the HTTP transport and put in a container. Then it's deployed to a cloud instance. At no step did anyone decide to expose it publicly; at every step, it became a bit more true. Censys notes that 61.5% of the services found answered directly on a bare IP address, with no domain name, a sign of quick deployments rather than services designed to be public.
Docker adds a classic trap. Publishing a port with -p 8080:8080 opens it on every interface of the machine, and Docker writes its own iptables rules, which take effect before those of a firewall like ufw. An administrator who thinks the port is closed in ufw may have left it open to the world.
# exposed on every interface, and past ufw docker run -p 8080:8080 my-mcp-server # reachable from this machine only docker run -p 127.0.0.1:8080:8080 my-mcp-server
What's exposed
Censys's numbers, obtained without ever calling a single tool (only from what servers announce during initialization), show the scale of the risk. 88.3% of servers expose at least one tool. About 90 advertise command execution tools, and 1,056 direct query interfaces to SQL, NoSQL or vector databases. The most represented categories are data (databases, knowledge bases) and infrastructure (system control, cloud management).
The arXiv study went further, with a dedicated testing framework covering ten MCP-specific vulnerability classes. Among the 68 reported flaws: SQL injection through tool arguments, SSRF to cloud metadata services, prompt template injection, path traversal. One detail makes the problem hard to track: 41.6% of confirmed servers had vanished between measurement runs, in under three days. Ephemeral servers, spun up for a trial and sometimes forgotten.
Authentication isn't enough
Censys makes the point: an authenticated MCP server is still exposed to prompt injection, since a legitimate client, the agent, calls it with arguments derived from untrusted content. Authentication closes the door to strangers; it doesn't protect against a manipulated agent.
Deploying an MCP server properly
- Stay on stdio as long as the server doesn't need to be shared. No port, no surface.
- Over local HTTP: bind to 127.0.0.1 and validate the Origin header, as the specification requires; otherwise a web page the developer visits can talk to the server through DNS rebinding.
- Over remote HTTP: implement the specification's OAuth 2.1 authorization, or at minimum put the server behind an authenticated gateway. Never a bare public IP.
- Reduce every tool to the strict minimum: a read-only database user rather than a free-form SQL tool, file paths restricted to one directory, no access to cloud metadata.
- Keep an inventory: a server started "just to test" and never stopped is exactly the one that ends up in the statistics.
When detektd finds an MCP endpoint on the scanned domain, it proceeds like Censys: it reads the list of announced tools, without ever calling one. Severity depends on what they allow: a server exposing a shell, file access, SQL queries or arbitrary HTTP calls without authentication is rated high.

Prompt injection isn't a bug you patch once
Researcher RyotaK ended up cataloguing around fifty separate ways to bypass Claude Code's permission system. The most critical one let an attacker steal CI/CD secrets in January 2026, starting from a single GitHub issue.

When a prompt becomes a shell: what Microsoft found in agent frameworks
In May, Microsoft's Defender research team published two critical CVEs in Semantic Kernel where prompt injection could end in code execution on the host machine. The problem isn't confined to one framework.