Sep 19, 2026·8 min read·20 visits
ToolHive failed to isolate local containerized MCP servers by default, allowing malicious containers to bypass isolation via host.docker.internal and access unauthenticated host-local APIs and databases.
A high-severity access control vulnerability in ToolHive CLI before v0.30.1 and ToolHive Studio before v0.38.0 allows local containerized MCP servers to bypass network isolation. This enables malicious workloads to establish TCP/IP connections to administrative and control plane endpoints exposed on the host loopback interface.
ToolHive is an orchestration framework designed to deploy and manage Model Context Protocol (MCP) servers, which allow Large Language Models (LLMs) to interact with external tools, APIs, and file systems. To run these tools safely, ToolHive supports running MCP servers inside containerized environments. The containerization model is intended to provide a security boundary, preventing untrusted or compromised MCP servers from accessing sensitive files or network assets hosted on the parent machine.
The vulnerability designated as CVE-2026-58197 represents a failure to enforce this isolation boundary. Prior to ToolHive CLI version 0.30.1 and ToolHive Studio version 0.38.0, the network configuration of these containers was left wide open by default. The platform allowed containerized applications to resolve and route network traffic directly back to the host machine through standard Docker virtual network paths, such as the host bridge gateway.
This architectural flaw exposes a significant attack surface. Because ToolHive's administrative control plane, local proxy configurations, and other adjacent microservices listen on localhost without requiring authentication, any containerized MCP server can communicate back to these interfaces. This vulnerability bypasses the intended sandbox, facilitating lateral movement from an isolated container to the broader host operating system.
The root cause of CVE-2026-58197 lies in an insecure default configuration combined with an implicit type conversion characteristic of the Go programming language. When ToolHive's backend API parses incoming JSON payloads to configure workload executions, it deserializes the payload into structure definitions. In Go, when a primitive type such as a boolean is omitted from a JSON string, the json.Unmarshal process automatically assigns the type's zero-value, which is false.
The structure defining the update request was modeled using a standard primitive boolean: NetworkIsolation bool. Because of this design choice, any client payload that omitted the network_isolation key would automatically cause the application to initialize the field to false. Instead of interpreting the absence of the key as an instruction to apply a secure-by-default profile, the application silently disabled network isolation. This left containers attached to the standard bridge network with full egress access to the host bridge interface.
Furthermore, ToolHive Studio, the graphical interface wrapper, contained a front-end implementation error where it explicitly transmitted "network_isolation": false in its payload structures. Even if a user intended to run an isolated container, the client application explicitly overrode this preference, sending a negative flag value to the API. This combination of unsafe JSON deserialization defaults in the CLI and explicit disabling in the GUI meant that almost all local container workloads ran without active network restrictions. Consequently, containerized processes could resolve DNS records like host.docker.internal and establish connections directly to ports listening on the host's loopback interface.
To understand the precise vulnerability mechanics, we must analyze the Go payload definition and the subsequent remediation. In the vulnerable implementation of the Go backend, the updateRequest struct in pkg/api/v1/workload_types.go used a raw boolean type. This made it impossible to distinguish between a client that explicitly requested isolation to be disabled and a client that omitted the field entirely.
// VULNERABLE STRUCT DEFINITION
type updateRequest struct {
ProxyMode string `json:"proxy_mode"`
// If this field is omitted from the JSON request payload,
// Go unmarshals it to its zero-value (false), disabling isolation.
NetworkIsolation bool `json:"network_isolation"`
}The remediation resolved this ambiguity by changing the field type to a pointer to a boolean (*bool). When unmarshaling JSON, an omitted field is mapped to nil, while an explicit boolean value maps to a pointer containing true or false. This allows the application logic to identify omitted fields and safely apply a secure-by-default logic gate.
// PATCHED STRUCT DEFINITION
type updateRequest struct {
ProxyMode string `json:"proxy_mode"`
// Pointer type allows distinguishing between nil (omitted) and false
NetworkIsolation *bool `json:"network_isolation,omitempty"`
}
// Helper function to resolve the boolean value with a secure default
func networkIsolationEnabled(v *bool) bool {
// If the field is omitted (nil), default to secure network isolation (true)
if v == nil {
return true
}
return *v
}In addition to this backend structural change, the CLI flag parser was updated in cmd/thv/app/run_flags.go to flip the default value of the network isolation parameter from false to true. This ensures that any command-line invocation that does not explicitly specify isolation parameters will run the container within an isolated network sandbox, closing the vulnerability for CLI users.
Exploitation of CVE-2026-58197 requires that a user deploy a malicious or compromised MCP server container. Since MCP servers are often downloaded from public repositories or third-party sources to perform tasks like text formatting, web scraping, or database querying, this constitutes a realistic vector. Once the user runs the container, the attacker-controlled code inside the container execution context initiates an automated reconnaissance scan against the Docker gateway IP.
The attack path progresses from the container namespace through the virtual bridge network to the host's IP space. In standard Docker configurations on macOS and Windows, host.docker.internal resolves to the IP address of the host machine. In Linux environments, the gateway interface (typically 172.17.0.1 or gateway.docker.internal) serves the same routing role. The script running inside the container attempts to establish TCP handshakes with sensitive local services listening on the host.
Because ToolHive's internal control plane endpoints are bound to the host's local loopback network interface without mandatory authentication tokens, the containerized process can invoke administrative commands. It can execute local HTTP POST requests to manage other containers, request sensitive credential payloads, extract environment variables, or execute arbitrary operations via other unisolated sibling MCP tools. The attacker achieves complete lateral movement and potential remote code execution on the host machine.
The security impact of this vulnerability is classified as high, receiving a CVSS v3.1 base score of 8.8. The primary risk lies in the complete compromise of the host's local environment. An attacker who successfully runs an MCP server container can interact with any service bound to localhost, effectively bypassing firewall rules that block external network access. This exposes developer workstations and internal build servers to critical risks.
Common local services that become vulnerable to compromise include local LLM engines such as Ollama, database servers, and development-stage Kubernetes APIs. By interacting with these interfaces, the malicious container can exfiltrate proprietary model weights, inject poison data into databases, or spin up unauthorized workloads. If the host machine has access to cloud provider metadata services or environment variables with cloud credentials, the attacker can leverage this access to compromise cloud environments.
Additionally, because ToolHive is designed to manage workloads, an attacker can manipulate the state of other deployed containers. By calling the administrative APIs on localhost, the malicious container can shut down security agents, spin up new malicious containers, or access logs containing high-value secrets. The failure to maintain container boundaries nullifies the core security benefit of containerized execution.
Remediation of CVE-2026-58197 requires updating both the ToolHive CLI and ToolHive Studio components to their patched releases. Administrators must deploy ToolHive CLI version 0.30.1 or later and ToolHive Studio version 0.38.0 or later. These versions incorporate the secure-by-default posture where the network isolation flag defaults to true, and empty API payloads default to enabling isolation.
In scenarios where immediate upgrades are not possible, administrators should implement manual workarounds. For CLI deployments, users must modify all execution scripts to explicitly include the isolation flag, overriding the insecure default. The command structure should be adjusted to: thv run --isolate-network=true <SERVER_NAME>. This ensures the container runtime configures restricted network namespaces.
For network-level protection, security teams can apply firewall configurations on the host machine. By defining rules in iptables or similar filtering utilities, hosts can block incoming traffic from Docker bridge subnets (typically 172.17.0.0/16) destined for sensitive local administrative ports. This defense-in-depth approach ensures that even if a container runs with an insecure network profile, the host operating system actively drops unauthorized connection attempts.
CVSS:3.1/AV:A/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
toolhive stacklok | < 0.30.1 | v0.30.1 |
toolhive-studio stacklok | < 0.38.0 | v0.38.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-284 / CWE-306 |
| Attack Vector | Adjacent Network (AV:A) |
| CVSS Base Score | 8.8 (High) |
| Exploit Status | No Public Exploit |
| CISA KEV Status | Not Listed |
| Impact | Privileged Host Access / Remote Code Execution via lateral APIs |
The software does not restrict or incorrectly restricts access to a resource from an unauthorized actor.
CVE-2026-44266 (GHSA-7w38-ggh5-v542) is a code injection vulnerability in @enspirit/elo prior to version 1.0.1. The Ruby target compiler fails to escape the hash character (#) when emitting double-quoted Ruby string literals and subtype constraint failure labels. An attacker who supplies crafted Elo expressions to an application compiling and executing Ruby output achieves arbitrary code execution.
CVE-2026-44267 is a sandbox escape and code injection vulnerability in @enspirit/elo prior to version 1.0.1. Due to unrestricted member access transformation in the compiler pipeline, plain Elo expression strings can traverse JavaScript object prototypes via .constructor.constructor to access the host runtime Function constructor. This allows attackers supplying untrusted Elo expressions to execute arbitrary JavaScript in Node.js server environments or client browser contexts.
CVE-2026-62374 (GHSA-f9j6-8p6x-r9j6) is a verification bypass vulnerability in the OpenWallet Foundation SD JWT JS library (@sd-jwt/core and @sd-jwt/decode versions 0.19.0 and earlier). Due to permissive UTF-8 decoding and the omission of mandatory reference checks during presentation verification, tampered or unreferenced disclosures are silently dropped rather than rejected. This deviates from RFC 9901 §7.1 requirements and allows attackers to execute silent claim-set reduction attacks against relying parties.
An interpretation conflict in Bytebase DBHub (< 0.22.6) allows attackers to bypass read-only SQL query restrictions when connected to MySQL or MariaDB instances. Because DBHub's custom SQL tokenizer treats any '--' sequence as a comment, whereas MySQL and MariaDB require trailing whitespace or a control character, crafted queries containing '--' immediately followed by non-whitespace characters allow stacked destructive SQL statements to execute on connections configured as read-only.
CVE-2026-118777 is a prototype pollution vulnerability (CWE-1321) in the Forge JavaScript cryptography and networking library (distributed on npm as node-forge) prior to version 1.4.1. The flaw resides in the forge.http client subsystem, where incoming HTTP cookie names and paths parsed from Set-Cookie response headers are stored directly into standard JavaScript objects without key validation or property isolation. By returning crafted Set-Cookie headers containing keys such as __proto__ or constructor, a malicious HTTP server can inject arbitrary properties into Object.prototype, attach attributes to the global Object constructor, or delete built-in prototype methods to cause an application-wide denial of service.
CVE-2026-118775 (GHSA-4642-5mcj-2rqw) is an integer overflow and validation flaw in the ASN.1 serialization module of Forge (node-forge) prior to version 1.4.1. The asn1.oidToDer() function fails to validate the range of the first two arcs of an Object Identifier (OID) and truncates the packed initial subidentifier to a single 8-bit integer. Applications that perform policy checks on untrusted OID strings before encoding them into Distinguished Encoding Rules (DER) format can be tricked into emitting DER bytes that correspond to a completely different, restricted OID.