Skip to content

(feat) Harden user-MCP http SSRF guard (DNS rebinding + redirects) for OSS default-on #4911

Description

@mmabrouk

User MCP servers are now on by default in OSS. An agent author controls the mcpServers[].url in their config, and the runner sends the run's Agenta-resolved named secrets as request headers to that URL. We want a self-hoster to leave user MCP on without an author-controlled config being able to reach an internal host and exfiltrate a credential.

Today the SSRF guard checks only the URL scheme and the host literal. validateUserMcpUrl in services/agent/src/engines/sandbox_agent/mcp.ts requires https and rejects loopback, link-local, cloud-metadata (169.254.169.254), and private-IP host literals, with a AGENTA_AGENT_MCP_HOST_ALLOWLIST opt-out. That is scheme + host only. It does not:

  • pin the connection to the host it validated, so a hostname that resolves to a public IP at check time can resolve to 127.0.0.1, 169.254.169.254, or a private IP when the harness actually connects (DNS rebinding); and
  • re-validate redirects, so a validated public https URL can 3xx-redirect the credentialed request to an internal host.

The blast radius is bounded: secrets ride headers only to https hosts, and the capability is config-trust. But with OSS default-on this is a real residual.

Proposed hardening:

  • Resolve the URL host once, validate the resolved IP(s) against the same internal-range rules, and pin the connection to that IP so no second DNS lookup happens at connect time.
  • Set redirect: "manual" (or the equivalent) and re-run the origin/IP validation on each redirect hop before following it.

Reference the guard and its docstring at services/agent/src/engines/sandbox_agent/mcp.ts (validateUserMcpUrl and isInternalHost).

Decision for the default-on PR: harden first, or ship default-on with this residual tracked here.

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions