Skip to content

Add support for host allowlisting to Fetch server #2317

Closed

Description

@olaservo

Is your feature request related to a problem? Please describe.
The fetch MCP server currently allows connections to local/internal IP addresses without any restrictions, which poses a security risk. While the README has been updated with a caution notice, this reference implementation could be misused if deployed without proper safeguards.

Describe the solution you'd like
Implement a host allowlisting mechanism for the fetch server that would:

  • Allow administrators to specify which hosts/domains the server can connect to
  • By default, block connections to local/internal IP ranges (127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, etc.)
  • Provide configuration options to explicitly allow internal IPs if needed for specific use cases
  • Implement checks at the socket level to avoid TOCTOU (Time-of-Check-Time-of-Use) vulnerabilities

Describe alternatives you've considered

  • Leave as-is with documentation only: Continue with just the warning in the README, but this leaves the reference implementation vulnerable and sets a poor security example

Additional context

  • Consider adding example configurations to the Readme showing secure deployment patterns.

Activity

  1. changed the title [-]Add support for allowlisting to Fetch server[/-] [+]Add support for host allowlisting to Fetch server[/+] on Jul 10, 2025
  2. olaservo commented on Jul 10, 2025

    @olaservo
    MemberAuthor
  3. olaservo commented on Aug 17, 2025

    @olaservo
    MemberAuthor

    @claude lets implement this feature for the Fetch server.

  4. added
    server-fetchReference implementation for the Fetch MCP server - src/fetch
    on Aug 17, 2025
  5. claude commented on Aug 17, 2025

    @claude
    Contributor

    Claude finished @olaservo's task —— View job • claude/issue-2317-20250817-1707 • Create PR ➔


    Implementation Complete ✅

    I've successfully implemented the host allowlisting feature for the Fetch server to address the security concerns in issue #2317.

    Changes Made

    Security Features Implemented:

    • Default IP Blocking: Blocks access to local/internal IP ranges by default (127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, link-local, multicast, IPv6 equivalents)
    • Host Allowlisting: --allowed-hosts argument supports exact domains and wildcards (*.example.com)
    • Development Override: --allow-private-ips flag allows internal IPs when needed
    • Custom IP Restrictions: --blocked-ip-ranges for additional CIDR blocks
    • TOCTOU Prevention: Socket-level hostname resolution validates IPs before connection

    Files Modified:

    • src/fetch/src/mcp_server_fetch/server.py: Added IP validation, hostname resolution, and allowlist logic
    • src/fetch/src/mcp_server_fetch/__init__.py: Added new command-line arguments
    • src/fetch/README.md: Updated with security documentation and configuration examples

    Configuration Examples:

    // Allow specific domains only
    {
      "mcpServers": {
        "fetch": {
          "command": "uvx",
          "args": ["mcp-server-fetch", "--allowed-hosts", "example.com", "*.github.com"]
        }
      }
    }

    Testing: All IP validation logic verified with comprehensive test cases covering IPv4/IPv6 ranges.

    Todo List:

    • Read repository structure and CLAUDE.md guidelines
    • Locate and analyze existing Fetch server implementation
    • Design host allowlisting architecture
    • Implement IP range validation and blocking
    • Add configuration options for allowlisting
    • Implement socket-level checks to avoid TOCTOU vulnerabilities
    • Update documentation and README
    • Test the implementation
    • Commit and push changes
  6. domdomegg commented on Aug 17, 2025

    @domdomegg
    Member

    Will flag that I think many people (myself included) use the fetch MCP intentionally to hit local endpoints, e.g. for testing out servers on localhost while developing. I don't know what others expect, but changing the default could be a surprise for many people.

  7. olaservo commented on Aug 19, 2025

    @olaservo
    MemberAuthor

    @domdomegg I think thats a good point. If we were doing this from scratch I think that we would offer some kind of 'use dangerously' flag that could get set by the user, vs defaulting to the more open behavior? But I agree that breaking the existing behavior will be disruptive. I think the question is whether we think the disruption is worth the benefit. @jenn-newton @dend what do you think?

  8. yakuphanycl commented on Apr 26, 2026

    @yakuphanycl

    External MCP audit corroborates this gap.

    We ran the mcp-audit skill against mcp-server-fetch@0.6.3 on 2026-04-26. The audit confirms the SSRF posture this issue tracks:

    • Current state: tool fetches arbitrary URLs with no IP filter, no host allowlist, no --allowed-hosts runtime guard. README [!CAUTION] block warns operators at install time.
    • Severity per the audit's framework: SEC-004 (default High) → de-escalated to Low because this is a maintainer-tracked, documented limitation, not a fresh discovery.
    • Reference: full case-study at yakuphanycl/wrg-skills/docs/case-studies/fetch-mcp-2026-04-26.md (PR pending merge).

    We noted the unmerged branch claude/issue-2317-20250817-1707 (commit a1226d4) which already implements --allowed-hosts, CIDR blocking for private ranges, --allow-private-ips opt-out, and --blocked-ip-ranges. If the reasons it didn't land are addressable, we'd be glad to rebase it onto current main and open a fresh PR. If there's a design reason it shouldn't land in that shape, a pointer to the discussion would help us file the right alternative.

    No urgency from our side — this issue's enhancement label matches our severity assessment.

  9. g-yixuan commented on Sep 6, 2026

    @g-yixuan

    I'd like to pick this up and prepare a fresh PR (with a current base, per the note on #2568).

    Design proposal — feedback welcome:

    Scope: opt-in host allowlisting only, no change to default behavior.

    • New --allowed-hosts HOST [HOST ...] CLI flag. When unset, behavior is exactly as today (all hosts allowed), so users who intentionally fetch localhost/internal endpoints (@domdomegg's point) are unaffected.
    • When set, the fetch tool only connects to listed hosts:
      • exact match, case-insensitive: example.com
      • wildcard: *.example.com matches example.com itself and any subdomain
      • IP literals match literally
    • Enforced on the initial request and every redirect hop (switching from follow_redirects=True to a bounded manual redirect loop), and on the robots.txt pre-check — so the allowlist can't be bypassed via a 302 from an allowed host.
    • Fail-closed with a clear error message that does not echo the configured allowlist.

    What I'm deliberately not including:

    On the TOCTOU bullet: with a hostname allowlist, the validated hostname is exactly what gets connected (SNI/Host), so DNS check-time/connect-time skew does not weaken the control; per-hop re-validation closes the redirect bypass, which is the realistic escalation path.

    Will include full unit tests (exact/wildcard/IP matching, redirect-hop enforcement, robots.txt path, unset-flag regression) plus README examples of secure configuration.

  10. g-yixuan commented on Sep 12, 2026

    @g-yixuan

    Follow-up: the PR is ready — #4770. Scope is opt-in --allowed-hosts only (no change to default behavior, per the discussion above), CI is green, and the design matches the proposal in my earlier comment. Happy to adjust scope or coordinate with #4497/#4773 if a different direction is preferred.

  11. cliffhall commented on Oct 19, 2026

    @cliffhall
    Member

    Triage: Priority Low (total 5)

    • Severity 3: fetch now refuses private destinations by default, but an operator-set host allowlist, which this asks for, does not exist yet.
    • Urgency 1: no time pressure
    • Bonuses: +1 high engagement

    Board: Servers V2 (#43), Status Incoming, awaiting maintainer review (no milestone yet). Part of the backlog triage in #4875.

  12. cliffhall commented on Oct 20, 2026

    @cliffhall
    Member

    Prior work, from the PR backlog triage (#4877). These outside pull requests addressed this issue against the pre-refactor code:

    They are being closed as part of the backlog triage in #4875, since the repository now takes issues rather than outside PRs and their diffs predate the v2 refactor. They stay readable and serve as prototypes for the fix here. Thank you to their authors.

  13. added this to the v2.3.0 milestone on Oct 25, 2026
  14. self-assigned this
    on Oct 28, 2026
  15. cliffhall commented on Oct 29, 2026

    @cliffhall
    Member

    Shipped in #5392 (merged into v2/main), after the #5271 rollup proved the six fetch v2.3.0 PRs combine with no conflicts.

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

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestserver-fetchReference implementation for the Fetch MCP server - src/fetchv2

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions