🛡️ CVE-2026-58196 — toolhive
Description
ToolHive: SSRF in remote MCP server authentication discovery (host-side, bypasses container isolation)
# Security Advisory: SSRF in remote MCP server authentication discovery
Severity: High. CWE: CWE-918. Affected: ToolHive through the latest release v0.29.3 and current main (HEAD b672d82f, 2026-06-12; re-verified 2026-06-14). FetchResourceMetadata and the discovery clients remain unguarded; no commits to pkg/auth/discovery or pkg/auth/remote address this. Originally identified at commit 05f11b53; all line references below are against HEAD b672d82f.
Summary
ToolHive's remote MCP server authentication discovery issues outbound HTTP requests to URLs the remote MCP server controls, with no private-IP or loopback guard and no restriction on redirects. ToolHive's core security model treats every MCP server as untrusted: the README states it "runs every MCP server in an isolated container" with "no local credentials," and it ships an egress proxy for network isolation. This discovery code runs host-side, in the ToolHive process, before and outside that per-server container sandbox. A malicious or compromised remote MCP server, added by a user through ToolHive's normal remote-server workflow, can therefore drive the ToolHive host itself to fetch arbitrary internal URLs, including cloud instance metadata, which bypasses the isolation ToolHive exists to provide. The user never selects a malicious target; they connect to a server they intend to use, and the attack is carried entirely in that server's discovery response.
ToolHive already establishes this boundary in code. ValidateRemoteURL (cmd/thv-operator/pkg/validation/url_validation.go:61) rejects internal IPs and known internal hostnames for the configured remote URL, and IsPrivateIP (pkg/networking/utilities.go:105) blocks RFC1918, link-local, 169.254.0.0/16, and loopback for outbound requests. The discovery clients below never call either guard, and the attacker-supplied resource_metadata URL and its redirect target are validated by neither. This is a deviation from the project's intended behavior, not a configuration choice by the operator.
The discovery clients are explicitly marked as trusted
The three outbound requests in this finding carry the maintainers' own gosec suppressions, each with a rationale comment asserting the URL is trusted:
discovery.go:165--resp, err := client.Do(req) // #nosec G704 -- targetURI is the MCP server endpoint URL from internal configdiscovery.go:219--resp, err := client.Do(req) // #nosec G704 -- uri is built from the MCP server endpoint for auth discoverydiscovery.go:931--resp, err := client.Do(req) // #nosec G704 -- URL is the OIDC well-known metadata endpoint
gosec's G704 is its SSRF taint-analysis rule: it flags exactly this pattern, an HTTP request whose URL flows from external input. The suppressions dismiss it on the premise that the URL comes "from internal config" or is "the MCP server endpoint." That premise is the bug. The targetURI is the remote MCP server endpoint, and the resource_metadata URL at line 931 comes straight from the server's WWW-Authenticate header (parsed by ParseWWWAuthenticate, discovery.go:293; resource_metadata extracted at discovery.go:315). Under ToolHive's own threat model the remote MCP server is untrusted, so "the MCP server endpoint" is attacker-controlled input, not internal config. A parallel cluster of //nolint:gosec // G706 (log-injection) suppressions on the same discovery responses (discovery.go:212, 221, 240, 268, 273, 280) shows the same data being treated as trusted throughout this code path. The maintainers saw the taint-analysis warning on these requests and waved it through on a trust assumption that contradicts the project's design.
Relationship to existing reports
This is distinct from issue #5135 (DCR resolver SSRF). #5135 is scoped to the DCR registration client, which already refuses redirects: client.CheckRedirect = errDCRRedirectRefused (pkg/auth/dcr/resolver.go:1281), with an in-code comment explaining that the wrapping client "refuses to follow HTTP redirects ... never for a redirected request whose URL the upstream chose" (resolver.go:1240). The discovery sinks below set no CheckRedirect and no private-IP guard, and are reached by a different path (the WWW-Authenticate resource_metadata discovery and the OIDC issuer discovery). The project demonstrably understands that redirect-following to an upstream-chosen URL is dangerous and guarded the DCR client against it; it left the discovery clients open. Fixing #5135 does not address them.
This is also distinct from GHSA-pph6-vfjv-vpjw (published 2026-06-04), which reports that the IsPrivateIP guard itself misses the IPv6 NAT64 ranges and so requires a NAT64/DNS64 gateway to reach internal addresses. The finding here does not depend on that guard's completeness: the discovery clients never call IsPrivateIP at all, so the host fetches `169
How this vulnerability can be exploited
This issue can be reached over the network, attack complexity is low, an attacker needs no privileges on the target. No user interaction is required. Rated impact: confidentiality low, integrity none, availability none.
Weakness class
CVE-2026-58196 is classified as CWE-918: Server-Side Request Forgery (SSRF). The server fetches a URL supplied by the caller, which can be pointed at internal systems it alone can reach.
Affected software
CVE-2026-58196 is recorded against 1 package.
- github.com/stacklok/toolhive
Timeline and source
Published on 15 July 2026 and last revised on 21 July 2026. No public exploit is currently recorded for this entry. Record sourced from OSV.
References
Details
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N/E:P
Affected Packages
| Software | From version | Fixed in |
|---|---|---|
| github.com/stacklok/toolhive | — | — |
References
Similar Threats
- Low CVE-2026-54450
More CVE 2026 advisories
Browse all of CVE 2026 in the advisory index.
Free Vulnerability Check
Is your site affected by CVE-2026-58196?
BotEraser helps you identify potentially vulnerable plugins and themes by checking your installation against CVE-2026-58196 and other known CVE records.
Scan My Site Free →No credit card required · Results in minutes
ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.