
Autopsy 08 · MCP trust boundary · Comic Strip 6 A free MCP from the internet!
Would Ethosure have caught this? The Sentry MCP server SSRF
A self-hosted Sentry MCP server accepted a caller-controlled endpoint argument and passed it directly to an HTTP client. Any agent connected to the server could be redirected against internal infrastructure. The fix is not one CVE. The fix is treating every MCP server as an untrusted tool provider until a policy gate proves otherwise.
The incident
On July 12, 2026 an independent researcher opened GitHub issue #2 on the ddfourtwo/sentry-selfhosted-mcp repository, reporting a server-side request forgery in the raw_sentry_api component. The vulnerability is tracked as CVE-2026-81421. The raw_sentry_api tool accepted a caller-controlled endpoint argument and passed it directly to Axios request methods without validation; Axios processes absolute URLs, so a JSON-RPC call could set the endpoint to a local address such as http://127.0.0.1:8000/ssrf-proof and force the MCP server to initiate an outbound request to any destination. Tenable assigned CVSS 7.3; researchers argue 9.0. Forty-six days passed between the initial report and the CVE assignment with no maintainer response. Related work reported public Sentry DSNs usable as an attack vector against AI agents with an 85 percent success rate across 2,388 organisations.
- Yahoo Tech — Sentry MCP server SSRF exposes how agent trust chains become attack vectors
- Ibid. — NVD — CVE-2026-81421
- Ibid. — Forkast — Sentry MCP server SSRF exposes how agent trust chains become attack vectors
The applicable coding-ethos policy
tool-provider-untrustCoding-ethos policies are compiled from principle-owned CEL expressions. Every expression in the Ethosure corpus passes three gates: policyvalidate (schema + CEL compile), audit_runtime.py (the fields the expression references are guaranteed present on the runtime event path), and policytest (behavioral fixtures — the policy fires on the positive case and stays quiet on the near miss). The corpus ships 190 policies across 49 principles in six packs, with 422 fixtures and zero failures.
Walkthrough
- The vulnerability class is old — SSRF against an HTTP client that accepts absolute URLs. What is new is the surface. MCP servers are how agents pick up tools at runtime. Most enterprises do not yet treat them as untrusted third-party code. The policy answer is to require every MCP tool invocation to declare its destination and to check that destination against an allowlist before the call leaves the runtime.
mcp.tool_call.destination_allowlistfires onPreToolUsefor any MCP tool invocation whose resolved destination — including URLs reachable through tool-input parameters — is not on the workload’s allowlist. It returns severityblock. This is a runtime gate: the MCP server’s own input validation is treated as untrusted.mcp.server.provenance_requiredis the companion. The Sentry case is the pattern: a community maintainer, no signed release process, forty-six days of silence on a public issue. The expression fires when an agent attempts to register a new MCP server whose publisher identity is not on the trust list or whose latest release is not signed by a key in the registry.mcp.tool_input.no_absolute_url_in_endpoint_argumentis the direct class-of-attack policy. The expression fires on any tool call whose input contains a parameter namedendpoint,url,uri, ortargetwhose value parses as an absolute URL to a destination outside the workload’s allowlist. This closes the exact primitive Axios used to reach internal infrastructure.
Policy YAML
# Pack: model-provider-governance (v2)
# Inherits: regulated-enterprise-base
principles:
- id: tool-provider-untrust
title: Tool Provider Untrust
directive: >-
Treat every MCP server as an untrusted tool provider. Validate destinations,
require publisher provenance, and reject caller-controlled absolute URLs in
endpoint arguments.
policy:
expressions:
- id: mcp.tool_call.destination_allowlist
scope: agent_action
severity: block
event: PreToolUse
principle_ids:
- tool-provider-untrust
- security-by-design
skill_id: mcp-runtime-gating
when: >
tool_call.transport == "mcp"
&& !workload.egress_allowlist.exists(a,
tool_call.resolved_destination.matches(a))
message: >-
MCP tool call resolved to a destination outside the workload's allowlist.
advice: >-
Add the destination to the workload allowlist with a signed change entry, or reject
the call. The MCP server's own input validation is not authoritative.
- id: mcp.server.provenance_required
scope: agent_config
severity: block
event: MCPServerRegister
principle_ids:
- tool-provider-untrust
- radical-visibility
when: >
!registry.publishers.exists(p, p.id == mcp_server.publisher_id)
|| !mcp_server.latest_release.signed_by.exists(s,
registry.trusted_keys.exists(k, k == s))
message: >-
MCP server registration lacks a trusted publisher or a signed release.
advice: >-
Reject the registration until the publisher is added to the trust registry and the
release is signed by a trusted key. Community MCP servers without a signed release
process are treated as untrusted.
- id: mcp.tool_input.no_absolute_url_in_endpoint_argument
scope: agent_action
severity: block
event: PreToolUse
principle_ids:
- tool-provider-untrust
- security-by-design
when: >
tool_call.transport == "mcp"
&& tool_call.input_params.exists(p,
p.name in ["endpoint", "url", "uri", "target"]
&& p.value.is_absolute_url
&& !workload.egress_allowlist.exists(a, p.value.matches(a)))
message: >-
MCP tool input contains a caller-controlled absolute URL outside the allowlist.
advice: >-
Reject absolute URLs in endpoint-shaped arguments. The Sentry MCP SSRF used exactly
this primitive to force outbound requests to internal addresses.
Assurance boundary. Fixtures prove that synthetic positive cases fire and near-misses stay quiet. They do not establish production alert rates. DLP-backed controls depend on upstream detection, shell-command regexes are defense in depth rather than a sandbox boundary, and regulatory tags are engineering aids requiring counsel review.
Where this policy lives in the corpus
The Ethosure importable corpus ships six coding-ethos packs. Each pack composes with the regulated-enterprise base pack, which owns cross-cutting controls for secrets, destructive actions, and human oversight.
- Regulated-enterprise base pack — secrets, destructive actions, human-in-the-loop, evidence-layer recording.
- Financial services overlay — OSFI E-23 alignment, FINTRAC-adjacent data handling, transaction-boundary controls.
- Healthcare & life sciences overlay — PHI handling, model-provenance requirements, evaluation-set contamination checks.
- Government & critical infrastructure overlay — identity-provenance requirements, review-channel signatures, air-gap enforcement labels.
- Model & provider governance pack — egress allowlists, evaluation-runtime isolation, cross-runtime coordination detection.
- AI cost control pack — payload-size and endpoint-visible model checks (preventive), token-total and response-side model facts (detective), external ledger for cumulative budgets.
Published September 3, 2026 · Ethosure · Part of the Autopsy Series.