Skip to content

Decide the MCP URL policy (HTTPS, allowlist, ADR?) #108

Closed

Description

@tonibergholm

Question

The policy half of audit finding #4: what restrictions apply to operator-configured MCP fingerprinting URLs? This constrains what operators may configure, so it is a product/config-surface decision (HITL), not a straight fix. SSRF exposure from configured URLs is the driver.

To settle:

  • HTTPS-only? With a loopback/localhost exception for local dev (the demo fingerprints local MCP servers)?
  • Operator allowlist: hard-require, or optional with default-warn?
  • Does the change warrant a short ADR (it changes the daemon's operator-facing config contract)?

Resolution records: the decided policy, ADR yes/no (and number if yes). The implementation ticket is blocked on this.

Activity

  1. self-assigned this
    on Jul 9, 2026
  2. tonibergholm commented on Jul 9, 2026

    @tonibergholm
    MemberAuthor

    Resolution (grilling session with Toni, 2026-07-09)

    Decided policy, three parts:

    1. HTTPS required except loopback. Non-loopback http:// MCP URLs are rejected at daemon startup with a typed, loud error; http:// stays permitted for localhost / 127.0.0.0/8 / ::1. No --insecure-allow-http escape hatch in v1.0 — remote-plaintext MCP is not a supported shape even behind friction (the ADR-0012 escape-hatch precedent existed because the demo needed it; the demo doesn't configure MCP at all).
    2. Redirect-following disabled (reqwest::redirect::Policy::none()) on the daemon's HTTP client. This is the half with a genuine remote attacker: a compromised configured server could 30x the fingerprinting POST to internal endpoints (Cloud Run metadata server) and the response would be canonicalised and persisted into the commit tree — SSRF plus exfiltration into the object store, unstoppable by any startup URL check. A redirect response becomes a per-server fingerprint error naming the Location target. The shared DaemonState.http client gets a comment pinning this: future non-MCP uses that want redirects must build their own client.
    3. No separate allowlist — addressed by construction, not skipped. --mcp name=url is already an explicit operator enumeration; with schemes validated and redirects off, the destination set equals the configured list exactly, so a second host list would restate the first with extra ceremony. The reasoning goes in the ADR so the audit finding reads as consciously closed.

    ADR: yes — ADR-0016, a one-pager in ADR-0001's format, drafted as part of the implementation ticket. It changes the operator-facing startup contract (previously-valid remote http:// URLs now abort startup) and pins the SSRF posture in one citable place.

    Facts surfaced during the session: MCP URLs enter only via the --mcp startup flag (operator-controlled, never socket input); run-demo.sh passes no --mcp at all, so the demo is unaffected; the current client follows up to 10 redirects (reqwest default) — the live vector item 2 closes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

wayfinder:grillingWayfinder ticket: HITL decision via /grilling

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions