Your MCP Server Is Listening on 0.0.0.0 and Accepting Anonymous Client Registrations JFrog Security Research disclosed CVE-2026-90898, a CVSS 9.8 flaw in the open-source Bifrost AI gateway that lets an unauthenticated attacker achieve remote command execution by POSTing a stdio-type MCP client registration to the management API, which the official Docker image binds to 0.0.0.0 with authentication disabled by default. Because Bifrost spawns the specified command immediately without waiting for an MCP handshake, a single request can run shell commands as appuser and exfiltrate environment variables containing API keys for every connected LLM provider. The issue is patched in transports/v2.1.0, which returns 403 for unauthenticated stdio registration, though the researcher notes MCP itself defines no client authentication mechanism. Bifrost is an open-source AI gateway that sits between your application and your LLM providers. It handles routing, load balancing, and fallback logic for models from OpenAI, Anthropic, Google, and about a dozen others. It also speaks MCP, the Model Context Protocol, which means it can register and manage tool-providing clients as part of the AI agent stack. Thousands of teams use it. The official Docker image ships with management authentication disabled and the API bound to 0.0.0.0 . One unauthenticated POST to /api/mcp/client gets you a shell. CVE-2026-90898. CVSS 9.8. Discovered by Yuval Moravchick at JFrog Security Research. Patched in transports/v2.1.0. If you're running anything in the 2.0.x or 1.6.x lines, your MCP management API is accepting anonymous client registrations right now. MCP supports multiple transport types. The one that matters here is stdio: a client type that launches a local subprocess and communicates with it over standard input/output. When you register a stdio MCP client through Bifrost's management API, the gateway spawns the specified command as its own process user. The stock Bifrost binary binds the management API to localhost by default. Limited exposure. The official Docker image overrides this to 0.0.0.0 , because containers need to accept connections from outside their network namespace. If you published the management port in your docker-compose.yml , which you probably did because the documentation shows you how, the API is now reachable from anywhere that can route to your host. Management authentication is disabled by default. The setting is governance.auth config.is enabled , and it defaults to false . The attack requires exactly one HTTP request. An attacker sends a POST to /api/mcp/client with a JSON body specifying a stdio-type connection: { "connection type": "stdio", "auth type": "none", "stdio config": { "command": "/bin/sh", "args": "-c", "id && cat /etc/passwd && env" , "tools to execute": " " } } Bifrost spawns /bin/sh immediately. It doesn't wait for the MCP handshake to complete. The HTTP request eventually times out because the spawned process isn't speaking MCP protocol back, but the command has already executed. The shell ran as appuser , which is the default user in the Bifrost Docker image. That env at the end of the command chain is the important part. In a running Bifrost instance, environment variables contain API keys for every connected LLM provider: OpenAI, Anthropic, Google, Cohere, whatever you've configured. One request, arbitrary command execution, and your entire provider key set exfiltrated. This is the third significant MCP-related vulnerability in the past month. On September 6, Bifrost itself caught a separate flaw CVE-2026-86242, CVSS 8.1 . On September 14, the broader MCP ecosystem was dealing with tool description injection attacks where malicious tool metadata could manipulate agent behavior. And that's just the named CVEs. The protocol's attack surface is expanding faster than the security model can keep up. The fundamental problem: MCP has no client authentication story. The protocol defines tool providers and tool consumers, but the registration mechanism for new clients is left to the transport implementation. Bifrost's implementation was "accept the POST and spawn the process." No token, no certificate, no challenge. The fix in transports/v2.1.0 returns a 403 for unauthenticated stdio registration, which is the right answer, but it's a patch on a design gap. If you're deploying MCP-enabled infrastructure in production, your security posture depends on every gateway, proxy, and transport layer having independently implemented client authentication correctly. There's no protocol-level guarantee. Every implementation is rolling its own auth story, and some of them are rolling "none." Teams running persistent agent deployments with frameworks like those covered in the OpenClaw Automation Bible https://numbpilled.gumroad.com/l/openauto should audit every MCP endpoint in their stack. The YAML configs that define your agent topology are also your attack surface map. If a config specifies a stdio transport, the underlying gateway better require authentication before spawning anything. If you're running Bifrost in Docker, check your compose file first: Vulnerable: management port published, auth disabled services: bifrost: image: bifrost-ai/bifrost:2.0.0 ports: - "8080:8080" Management API exposed environment: - BIFROST AUTH ENABLED=false Default Test whether the management API is reachable: bash $ curl -s http://your-bifrost-host:8080/health If this returns 200, the management API is accessible Check the version: bash $ curl -s http://your-bifrost-host:8080/api/version Anything below transports/v2.1.0 is vulnerable If you can't upgrade immediately, enable authentication: governance: auth config: is enabled: true admin username: "admin" admin password: "something-that-isnt-the-default" And restrict the management listener to trusted networks. If you're behind a reverse proxy, don't expose port 8080 at all. The management API should never face the internet. If your Bifrost instance was internet-facing with authentication disabled for any period, assume compromise. The remediation sequence: /api/mcp/client . appuser account in Docker has limited privileges, but depending on your container configuration, an attacker may have written to mounted volumes or established outbound connections. bash Search for suspicious MCP client registration attempts $ docker logs bifrost 2 &1 | grep -i "mcp/client" Check for unexpected outbound connections during the exposure window $ docker logs bifrost 2 &1 | grep -E " curl|wget|nc |ncat " The MCP ecosystem is moving fast. New gateways, new transport implementations, new client libraries, all shipping features faster than they're shipping security reviews. Bifrost is open-source, well-maintained, and had JFrog's security research team actively looking at it. They still shipped a CVSS 9.8 in their default Docker configuration. The uncomfortable question for anyone running MCP in production: if a maintained, actively-audited gateway shipped with authentication disabled and the management API bound to all interfaces, what's lurking in the smaller, less-scrutinized MCP implementations in your stack? Every MCP transport endpoint is a registration surface. Every registration surface that accepts unauthenticated requests is a shell waiting to happen. The protocol doesn't enforce this boundary. Your infrastructure has to. If you want a framework for building and securing persistent agent deployments, including the MCP transport hardening that the protocol itself doesn't give you, I put together a production-focused system at numbpilled.gumroad.com https://numbpilled.gumroad.com/l/paperclip-claude-method covering the full agent lifecycle from deployment through operational security. Written with AI assistance. Technical content, methodology, and voice are mine.