You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add support for host allowlisting to Fetch server #2317
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.
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
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.
@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?
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.
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.
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.
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.
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.
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.
Activity
[-]Add support for allowlisting to Fetch server[/-][+]Add support for host allowlisting to Fetch server[/+]olaservo commentedon Jul 10, 2025
cc @dend @jenn-newton
olaservo commentedon Aug 17, 2025
@claude lets implement this feature for the Fetch server.
claude commentedon Aug 17, 2025
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:
--allowed-hostsargument supports exact domains and wildcards (*.example.com)--allow-private-ipsflag allows internal IPs when needed--blocked-ip-rangesfor additional CIDR blocksFiles Modified:
src/fetch/src/mcp_server_fetch/server.py: Added IP validation, hostname resolution, and allowlist logicsrc/fetch/src/mcp_server_fetch/__init__.py: Added new command-line argumentssrc/fetch/README.md: Updated with security documentation and configuration examplesConfiguration Examples:
Testing: All IP validation logic verified with comprehensive test cases covering IPv4/IPv6 ranges.
Todo List:
Add host allowlisting and IP blocking to Fetch server
domdomegg commentedon Aug 17, 2025
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.
olaservo commentedon Aug 19, 2025
@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?
yakuphanycl commentedon Apr 26, 2026
External MCP audit corroborates this gap.
We ran the
mcp-auditskill againstmcp-server-fetch@0.6.3on 2026-04-26. The audit confirms the SSRF posture this issue tracks:--allowed-hostsruntime guard. README[!CAUTION]block warns operators at install time.SEC-004(default High) → de-escalated to Low because this is a maintainer-tracked, documented limitation, not a fresh discovery.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(commita1226d4) which already implements--allowed-hosts, CIDR blocking for private ranges,--allow-private-ipsopt-out, and--blocked-ip-ranges. If the reasons it didn't land are addressable, we'd be glad to rebase it onto currentmainand 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
enhancementlabel matches our severity assessment.g-yixuan commentedon Sep 6, 2026
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.
--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.fetchtool only connects to listed hosts:example.com*.example.commatchesexample.comitself and any subdomainfollow_redirects=Trueto 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.What I'm deliberately not including:
--allowed-hostsfor an explicit allowlist; fix(fetch): block SSRF to internal/metadata IPs by default #4497's posture for default-deny). It also differs from the stale Add host allowlisting and IP blocking to Fetch server #2568, which changed defaults.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.
feat(fetch): add opt-in host allowlisting via --allowed-hosts
feat(fetch): add opt-in host allowlisting via --allowed-hosts
g-yixuan commentedon Sep 12, 2026
Follow-up: the PR is ready — #4770. Scope is opt-in
--allowed-hostsonly (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.Add host allowlisting and IP blocking to Fetch server
cliffhall commentedon Oct 19, 2026
Triage: Priority Low (total 5)
Board: Servers V2 (#43), Status
Incoming, awaiting maintainer review (no milestone yet). Part of the backlog triage in #4875.cliffhall commentedon Oct 20, 2026
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.
cliffhall commentedon Oct 29, 2026
Shipped in #5392 (merged into
v2/main), after the #5271 rollup proved the six fetch v2.3.0 PRs combine with no conflicts.