Skip to content

fix(http): outbound fetch calls have no timeout or redirect control #159

@BryanFRD

Description

@BryanFRD

Problem

Every outbound HTTP call uses bare fetch with no timeout, no redirect policy, and no response-size cap on the network read:

  • apiRequestpackages/mcp-core/src/api-client.ts
  • exchangeCodeForTokenpackages/mcp-core/src/auth/oauth.ts
  • fetch_docspackages/mcp/src/tools/docs.ts (caps the stripped output at MAX_BYTES, but await res.text() reads the whole body into memory first, and follows redirects by default)

In fetch_docs the host comes from a fixed enum, but slug is concatenated unvalidated and redirects are followed silently, so a product host that 30x-redirects offsite would be followed without the host allowlist applying to the final URL.

Why it matters

  • A hung or slow upstream (api.ferrlabs.com, a product marketing site, the OAuth exchange) blocks the tool call indefinitely — over stdio that wedges the whole MCP session with no error.
  • Following redirects past the vetted host defeats the point of the fetch_docs enum allowlist (mild SSRF surface).
  • res.text() with no streamed size guard lets a large/hostile response balloon memory before the post-hoc slice.

Proposed approach

  • Add an AbortController timeout (e.g. 15s, configurable) to all fetch calls; map abort to a clear tool error.
  • In fetch_docs, set redirect: 'manual' (or re-check the final URL host against the allowlist) and reject the slug if it contains ://, .., or a leading //.
  • Cap the read for fetch_docs by reading the stream incrementally and stopping at MAX_BYTES.

Acceptance criteria

  • A slow upstream produces a timeout error instead of hanging.
  • fetch_docs does not follow a redirect to a non-allowlisted host.
  • Tests cover timeout and redirect-rejection paths.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    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