Skip to content

Port v1's link-local/metadata destination guard to v2's /api/fetch proxy #2749

Closed

Description

@cliffhall

Problem

v1's /fetch proxy refuses link-local and cloud-metadata destinations (server/src/proxy-security.ts, #1717 / #1732). v2's equivalent, the backend POST /api/fetch route in core/mcp/remote/node/server.ts, has no destination guard: it accepts any scheme and follows redirects without re-checking them. The route carries the web client's OAuth traffic (discovery, protected-resource metadata, token, DCR/CIMD, revocation), and some of those URLs come from the server under test.

Proposed change

Port v1's guard to /api/fetch:

  • Scheme: http: / https: only.
  • Destinations: refuse link-local and metadata ranges only, matching v1: 169.254.0.0/16, its IPv4-mapped IPv6 forms, fe80::/10, fd00:ec2::254. Do not block loopback or RFC 1918, because local and LAN MCP servers and authorization servers are legitimate targets.
  • Redirects: follow them manually and re-validate every hop.
  • DNS: validate the resolved address and pin the connection to it (undici connect.lookup), so a name can't resolve differently between check and connect. Where createProxyFetch() routes through a corporate proxy, the proxy resolves DNS; decide and document what the guard can promise there.
  • Put the logic in its own coverage-gated module, not inline in server.ts.

Out of scope

The CLI and TUI make the same OAuth discovery requests directly from Node. Whether they should share the guard is a separate decision; note it in the PR.

Priority score

Severity 4, Urgency 3, +1 milestone, Total 8 → Medium.

Metadata

Metadata

Assignees

Labels

enhancementNew feature requestv2Issues and PRs for v2

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions