CVE-2026-58196: Verified Reproduction
CVE-2026-58196: ToolHive SSRF in remote MCP server authentication discovery
CVE-2026-58196 is verified against github.com/stacklok/toolhive · github. Affected versions: All ToolHive versions before 0.31.0. The GitHub repo advisory states ToolHive through v0.29.3 and main HEAD b672d82f41e6a919670ee1abe812f831ecb72448 were verified vulnerable before the fix. Vulnerability class: SSRF. This medium reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00290.
What Is CVE-2026-58196?
CVE-2026-58196 is a medium-severity server-side request forgery (CWE-918) in ToolHive before 0.31.0. During remote MCP server authentication discovery, the ToolHive host can be tricked into fetching an attacker-selected internal URL. Pruva reproduced it (reproduction REPRO-2026-00290).
CVE-2026-58196 Severity
CVE-2026-58196 is rated medium severity.
Medium — meaningful risk under specific conditions. Schedule a fix in the normal cycle.
Affected github.com/stacklok/toolhive Versions
github.com/stacklok/toolhive · github versions All ToolHive versions before 0.31.0. The GitHub repo advisory states ToolHive through v0.29.3 and main HEAD b672d82f41e6a919670ee1abe812f831ecb72448 were verified vulnerable before the fix. are affected.
How to Reproduce CVE-2026-58196
pruva-verify REPRO-2026-00290 curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00290/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-58196
- reached the target end-to-end
- full exploit chain demonstrated
- on the real production code path
- high confidence
- the upstream fix blocks the same trigger
remote MCP WWW-Authenticate resource_metadata URL and metadata 302 Location header
- ToolHive CLI: thv run <malicious-remote-url> --remote-auth
reproduction_steps.sh How the agent worked
Root Cause and Exploit Chain for CVE-2026-58196
- Affected versions: all versions before 0.31.0. The reproduction uses ToolHive v0.30.0 as the vulnerable build and v0.31.0 as the fixed negative control.
- Risk level and consequences: CWE-918 server-side request forgery. A malicious or compromised remote MCP server can cause the ToolHive host process, outside the intended per-server container isolation boundary, to fetch attacker-selected internal URLs. In a real deployment this can expose internal HTTP services or metadata endpoints reachable from the host.
Impact Parity
- Disclosed/claimed maximum impact: host-side SSRF during remote MCP server authentication discovery.
- Reproduced impact from this run: host-side HTTP GET from ToolHive v0.30.0 to an attacker-selected loopback canary URL after an attacker-controlled RFC 9728
resource_metadataendpoint issues a 302 redirect. - Parity:
full. - Not demonstrated: no secrets were targeted or exfiltrated. The lab intentionally used a local canary and recorded only request path, headers, and redirect behavior.
Root Cause
In vulnerable ToolHive v0.30.0, FetchResourceMetadata(ctx, metadataURL) in pkg/auth/discovery/discovery.go constructs a normal http.Client for a server-supplied RFC 9728 resource metadata URL. That client has no CheckRedirect policy and no private/loopback/link-local dial guard. Therefore, after the remote MCP endpoint returns WWW-Authenticate: Bearer ... resource_metadata="<attacker URL>", ToolHive fetches the attacker metadata URL and automatically follows HTTP 30x redirects to a different host/port. This occurs in the host-side authentication discovery path, before/outside any per-server container sandbox.
The v0.31.0 fix changes the discovery clients to enforce redirect and private-address protections: DetectAuthenticationFromServer and metadata/OIDC discovery use networking.SameHostRedirectPolicy(), FetchResourceMetadata accepts a blockPrivateIPs setting, and the protected HTTP transports can use networking.NewPrivateIPBlockingDialContext(). The same-host redirect policy refuses redirects to a different host:port and HTTPS-to-HTTP downgrades, which prevents the demonstrated cross-port loopback canary request.
Reproduction Steps
- Run
bundle/repro/reproduction_steps.sh. - The script:
- Uses the prepared project cache when available (
<project_cache_dir>/repoand<project_cache_dir>/bin) and downloads exact ToolHive release binaries for v0.30.0 and v0.31.0 if not already cached. - Starts a malicious remote MCP HTTP endpoint and a separate loopback canary HTTP endpoint in a closed lab network.
- Invokes the real product workflow twice per version:
thv run <malicious-url> --remote-auth --remote-auth-skip-browser --foreground. - The malicious MCP endpoint returns a
WWW-Authenticateheader with an attacker-controlledresource_metadataURL. That metadata endpoint returns a 302 redirect to the separate canary. - Records per-attempt ToolHive, malicious endpoint, and canary logs under
bundle/logs/, and writesbundle/repro/runtime_manifest.jsonbefore exit.
- Uses the prepared project cache when available (
- Expected evidence:
- ToolHive v0.30.0: both vulnerable attempts reach the malicious endpoint and the canary receives one ToolHive host-side request per attempt.
- ToolHive v0.31.0: both fixed attempts reach the malicious endpoint but the canary remains untouched.
Evidence
- Main run log:
bundle/logs/reproduction_steps.log- Shows two vulnerable successes and two fixed negative controls:
vulnerable attempt 1: malicious requests=6, canary requests=1vulnerable attempt 2: malicious requests=6, canary requests=1fixed attempt 1: malicious requests=6, canary requests=0fixed attempt 2: malicious requests=6, canary requests=0[CONFIRMED] CVE-2026-58196 reproduced with vulnerable/fixed divergence.
- Shows two vulnerable successes and two fixed negative controls:
- Vulnerable ToolHive product log:
bundle/logs/toolhive_vulnerable_attempt1.log- Confirms the real
thv runremote MCP workflow and host-side discovery path:Attempting to run remote MCP server: http://127.0.0.1:<port>Detected authentication requirement from serverwithresource_metadataset to the attacker endpoint.Fetching resource metadatafor that attacker URL.
- Confirms the real
- Malicious endpoint log:
bundle/logs/malicious_server_vulnerable_attempt1.log- Records the initial ToolHive request to
/, the RFC 9728 metadata redirect at/metadata-redirect/vulnerable/1, and the redirectlocationpointing at the separate canary URL.
- Records the initial ToolHive request to
- Canary log:
bundle/logs/canary_vulnerable_attempt1.log- Records the vulnerable host-side SSRF oracle:
method: GETpath: /internal-canary/vulnerable/1/metadata.jsonReferer: http://127.0.0.1:<malicious-port>/metadata-redirect/vulnerable/1User-Agent: Go-http-client/1.1
- Records the vulnerable host-side SSRF oracle:
- Fixed product logs:
bundle/logs/toolhive_fixed_attempt1.log,bundle/logs/malicious_server_fixed_attempt1.log, andbundle/logs/canary_fixed_attempt1.log- The fixed build reaches the malicious remote endpoint but the corresponding canary log stays empty, demonstrating the v0.31.0 redirect/private-dial protection blocks the canary fetch.
- Structured evidence manifest:
bundle/repro/runtime_manifest.json. - Attempt summary:
bundle/artifacts/toolhive-ssrf/attempts.jsonl.
Recommendations / Next Steps
- Upgrade ToolHive to v0.31.0 or later.
- Keep same-host redirect restrictions and private/loopback/link-local dial blocking on every HTTP client that fetches URLs derived from remote MCP server responses, including RFC 9728 metadata, OIDC discovery, and dynamic client registration discovery.
- Add regression tests for:
resource_metadataredirects to different host/port, redirects from public targets to private/loopback/link-local addresses, HTTPS-to-HTTP downgrade redirects, and DNS/private-IP rebinding during discovery. - Ensure future remote discovery features explicitly distinguish operator-configured trusted URLs from server-supplied URLs and apply stricter SSRF guards to the latter.
Additional Notes
- Idempotency confirmation:
bundle/repro/reproduction_steps.shwas run twice consecutively after finalization and succeeded both times with the same vulnerable/fixed divergence. - The lab does not contact real cloud metadata or third-party services. It uses a local malicious endpoint and a local canary as a safe stand-in for an internal service.
- The script attempts to bind a public-looking lab address for the remote endpoint, but if the sandbox cannot add/bind that address it falls back to loopback. The fixed-version negative control remains valid because v0.31.0 refuses the cross-host/cross-port redirect before the canary request is made.
CVE-2026-58196 Reproduction Transcript
The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired. Phases: support · claim contract · reproduction · judge · variant analysis
Full session Replay every step — scrub the timeline or play it back.
Artifacts and Evidence for CVE-2026-58196
Scripts, logs, diffs, and output captured during the reproduction.
How to Fix CVE-2026-58196
FAQ: CVE-2026-58196
Is the CVE-2026-58196 SSRF in the container sandbox or the host?
Which versions of ToolHive are affected by CVE-2026-58196?
How severe is CVE-2026-58196?
How can I reproduce CVE-2026-58196?
References for CVE-2026-58196
Authoritative sources for CVE-2026-58196 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.