CVE-2026-90898 Overview
Bifrost is an AI gateway that registers Model Context Protocol (MCP) clients through its management API. A stdio client registration accepts a command and arguments, and Bifrost starts that program the moment the client is added. No MCP handshake is required.
The default configuration sets governance.auth_config.is_enabled=false. With authentication disabled, every caller is treated as a local administrator. A single unauthenticated POST /api/mcp/client request executes an arbitrary program as the Bifrost process user, which is appuser on the official container image.
Critical Impact
Unauthenticated remote attackers can execute arbitrary commands on any Bifrost transports/v2.0.0 instance exposed to their network path, achieving code execution as the gateway process user.
Affected Products
- Bifrost transports/v2.0.0 and earlier
- Bifrost official container image (executes as appuser)
- Deployments running with default governance.auth_config.is_enabled=false
Discovery Timeline
- 2026-09-14 - CVE-2026-90898 published to NVD
- 2026-09-18 - Last updated in NVD database
Technical Details for CVE-2026-90898
Vulnerability Analysis
Bifrost exposes an MCP client registration endpoint at /api/mcp/client. Registering a stdio-transport client requires only a command string and argument list. Bifrost immediately spawns the specified process inside the gateway container without validating the caller and without performing an MCP handshake.
The shipping default disables authentication on the management API. Under that configuration, every HTTP request is treated as an authenticated administrator. An attacker who can reach the management port can register a malicious stdio client and trigger arbitrary command execution as the Bifrost process user. This maps to Improper Access Control [CWE-284].
The upstream fix in transports/v2.1.0 refuses unauthenticated stdio registrations with an HTTP 403 response. transports/v2.0.0 continues to permit the operation.
Root Cause
The root cause is an authorization gap in the MCP client management path. The endpoint that accepts stdio client definitions does not enforce authentication when governance auth is disabled, and no separate check gates the ability to launch child processes from user-supplied input.
Attack Vector
Exploitation requires network access to the Bifrost management API. The attacker sends a single HTTP POST to /api/mcp/client with a stdio client definition whose command and arguments describe the payload. Bifrost then executes that payload as appuser (on the official image) or as the process user of the gateway.
// Security patch in core/mcp/clientmanager.go - mcp auth with ssrf checks (#6757)
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
"github.com/maximhq/bifrost/core/mcp/utils"
+ "github.com/maximhq/bifrost/core/network"
"github.com/maximhq/bifrost/core/schemas"
)
+// mcpDialTimeout bounds each dial attempted by the SSRF-safe HTTP client MCP
+// client connections use, matching the timeout convention used by the other
+// SSRF-guarded outbound clients in this codebase (image/document fetch, skill
+// URL sources).
+const mcpDialTimeout = 10 * time.Second
+
// AcquireClientConn returns a live upstream MCP client connection for the
// given client state, along with a release function the caller must invoke
// (typically via defer).
Source: GitHub Bifrost Commit 12e1703
The patch also adds SSRF hardening for MCP HTTP transports:
// Security patch in core/network/ssrf.go - PrivateNetworkDialContext
+// PrivateNetworkDialContext returns a DialContext that, unlike
+// SSRFSafeDialContext, permits loopback, RFC1918/unique-local, and CGNAT
+// destinations. It still blocks link-local addresses (including the
+// 169.254.169.254 cloud metadata endpoint) and unspecified addresses, which
+// have no legitimate destination under any deployment topology. Same
+// DNS-rebinding protection as SSRFSafeDialContext: resolves once and dials
+// the validated IP directly.
+func PrivateNetworkDialContext(dialTimeout time.Duration) func(ctx context.Context, netw, addr string) (net.Conn, error) {
+ dialer := &net.Dialer{Timeout: dialTimeout}
+ return func(ctx context.Context, netw, addr string) (net.Conn, error) {
+ host, port, err := net.SplitHostPort(addr)
+ if err != nil {
+ return nil, fmt.Errorf("invalid dial address %q: %w", addr, err)
+ }
+ ips, err := net.DefaultResolver.LookupIP(ctx, "ip", host)
+ if err != nil {
+ return nil, fmt.Errorf("DNS lookup failed for %s: %w", host, err)
+ }
+ if len(ips) == 0 {
Source: GitHub Bifrost Commit 12e1703
Detect Identity Attacks the Moment Authentication Fails
Singularity™ Identity surfaces credential misuse, lateral movement, and privilege escalation in real time, so you can contain the breach before it spreads.
Stop Identity AttacksDetection Methods for CVE-2026-90898
Indicators of Compromise
- Unauthenticated HTTP POST requests to /api/mcp/client in Bifrost access logs
- Unexpected child processes spawned by the Bifrost gateway binary, particularly under the appuser account on containerized deployments
- New MCP client entries in Bifrost state referencing shells, interpreters, or download utilities as the stdio command
- Outbound network connections from the Bifrost container to unfamiliar hosts shortly after MCP client registration
Detection Strategies
- Alert on any POST /api/mcp/client request that arrives without a valid session or API token when governance.auth_config.is_enabled=false
- Baseline the process tree beneath the Bifrost gateway and flag deviations, especially executions of sh, bash, curl, wget, or python
- Inspect MCP client registrations for stdio command values that reference filesystem paths outside expected MCP server binaries
Monitoring Recommendations
- Forward Bifrost API access logs and container process telemetry to a centralized analytics platform for correlation
- Monitor egress traffic from the Bifrost host or pod for connections to non-approved destinations
- Track configuration drift on governance.auth_config and alert if authentication is disabled after being enabled
How to Mitigate CVE-2026-90898
Immediate Actions Required
- Upgrade Bifrost transports to v2.1.0 or later, which rejects unauthenticated stdio client registrations with HTTP 403
- Enable governance authentication by setting governance.auth_config.is_enabled=true and provisioning API credentials
- Restrict network exposure of the Bifrost management API to trusted administrative networks only
- Audit existing MCP client registrations and remove any entries not explicitly authorized
Patch Information
The fix is delivered in Bifrost transports/v2.1.0 via Pull Request #6757 and commit 12e1703. The patch enforces authentication on MCP client registration and adds SSRF protections for MCP HTTP transports. Project source is available at the GitHub Bifrost Project.
Workarounds
- Enable governance.auth_config.is_enabled=true and require API tokens for all management endpoints
- Place Bifrost behind a reverse proxy or service mesh that enforces authentication and IP allowlists on /api/mcp/*
- Run the Bifrost container as an unprivileged user with a read-only root filesystem and minimal outbound network egress
- Remove interpreters and download utilities from the container image to reduce post-exploitation utility
# Configuration example: enable governance auth and restrict management API exposure
governance:
auth_config:
is_enabled: true
# provision credentials via your secret store
api_tokens_source: env:BIFROST_API_TOKENS
# Example reverse-proxy allowlist (nginx)
# location /api/mcp/ {
# allow 10.0.0.0/8;
# deny all;
# proxy_pass http://bifrost_upstream;
# }
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

