modelcontextprotocol / modelcontextprotocol/servers

Security Hardening Recommendations for Fetch Server (SSRF Prevention)

Open
#3,741 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
90.5k
Forks
11.7k
Avg merge
2d 2h
Merged PRs (30d)
5

Description

Security Review: Fetch Server

I have been building MCP servers for production use (12 servers, 280+ tools deployed) and noticed some security considerations for the fetch server that could benefit the reference implementation:

1. URL Validation

Current:

const url = new URL(args.url);

Issue: This allows fetching from internal network addresses (169.254.x.x, 10.x.x.x, etc.) which could expose metadata services or internal APIs.

Recommendation:

const BLOCKED_HOSTS = [
  /^169\.254\./,  // Link-local
  /^10\./,        // Private A
  /^172\.(1[6-9]|2[0-9]|3[0-1])\./,  // Private B
  /^192\.168\./,  // Private C
  /^127\./,       // Loopback
  /^0\./,         // Current network
  /^::1$/,        // IPv6 loopback
  /^fc00:/i,      // IPv6 private
  /^fe80:/i,      // IPv6 link-local
];

function isUrlAllowed(url: URL): boolean {
  const hostname = url.hostname;
  return !BLOCKED_HOSTS.some(pattern => pattern.test(hostname));
}
2. Content-Type Validation

Current: No validation on returned content types.

Risk: Could fetch binary executables or malicious content.

Recommendation:

const ALLOWED_CONTENT_TYPES = [
  'text/html',
  'text/plain', 
  'text/markdown',
  'application/json',
  'application/xml',
];

// Validate before processing
const contentType = response.headers.get('content-type') || '';
if (!ALLOWED_CONTENT_TYPES.some(t => contentType.includes(t))) {
  throw new Error(`Content type not allowed: ${contentType}`);
}
3. Response Size Limits

Current: No limit on response size.

Risk: Memory exhaustion from huge responses.

Recommendation:

const MAX_RESPONSE_SIZE = 10 * 1024 * 1024; // 10MB

const contentLength = response.headers.get('content-length');
if (contentLength && parseInt(contentLength) > MAX_RESPONSE_SIZE) {
  throw new Error(`Response too large: ${contentLength} bytes`);
}
4. Timeout Configuration

Current: Uses default fetch timeout.

Risk: Hanging connections consuming resources.

Recommendation:

const FETCH_TIMEOUT = 30000; // 30 seconds

const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT);

try {
  const response = await fetch(url, { 
    signal: controller.signal,
    // ... other options
  });
} finally {
  clearTimeout(timeout);
}
5. Redirect Handling

Current: Default redirect behavior.

Risk: Open redirect vulnerabilities.

Recommendation:

const response = await fetch(url, {
  redirect: 'manual', // Handle redirects explicitly
  // ...
});

if (response.status >= 300 && response.status < 400) {
  const location = response.headers.get('location');
  // Validate redirect target before following
  const redirectUrl = new URL(location!, url);
  if (!isUrlAllowed(redirectUrl)) {
    throw new Error('Redirect to blocked host');
  }
}

Context

I run mcp-kali-orchestration and mcp-proxmox-admin in production environments where these security patterns are essential. Happy to discuss implementation details or contribute a PR.

Author: Eric Grill (https://ericgrill.com)
Related work: https://github.com/EricGrill/mcp-kali-orchestration

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the fetch server's URL-fetching entry point and review the five proposed areas: private-host validation, content types, response size, timeout handling, and redirects. Define tests for each security constraint and consider how the fetch server should report rejected requests; done means the agreed protections are implemented and covered by tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend, security
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.