MCP-NET-01 — URL Validation and SSRF Mitigation#
Level: L1
Domain: NET
Requirement#
MCP servers that fetch URLs MUST validate target addresses against an allowlist or MUST block private IP ranges, localhost, and cloud metadata endpoints.
Rationale#
Server-Side Request Forgery (SSRF) allows attackers to use the server as a proxy to access internal services, cloud metadata (AWS/GCP/Azure credentials), or perform port scanning.
Scope#
Tools that make HTTP/HTTPS requests, fetch web content, or resolve DNS.
Required Evidence#
- Code showing URL validation before fetch
- Blocked addresses include:
127.0.0.1,localhost,169.254.169.254,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 - Test: attempt to fetch
http://169.254.169.254/latest/meta-data→ expect rejection
Verification Guidance#
Static#
# Example validation
import ipaddress
from urllib.parse import urlparse
def is_safe_url(url):
parsed = urlparse(url)
# Resolve to IP
ip = socket.gethostbyname(parsed.hostname)
ip_obj = ipaddress.ip_address(ip)
# Block private/loopback/metadata
if ip_obj.is_private or ip_obj.is_loopback or ip_obj.is_link_local:
raise ValueError("Private IP access denied")
# Additional: check against allowlist if applicable
return TrueDynamic#
- Request
http://localhost:8080→ BLOCKED - Request
http://169.254.169.254→ BLOCKED - Request legitimate external URL → ALLOWED
Mappings#
- CWE: CWE-918 (Server-Side Request Forgery)
- OWASP Top 10: A10:2021 – Server-Side Request Forgery
- OWASP MCP Top 10: Implied in MCP-07 (Insufficient AuthN/AuthZ)
Exceptions & Compensating Controls#
NOT_APPLICABLE: Server has no network fetch capabilities. Compensating: Network-level egress filtering (firewall rules) provides additional protection but does not replace application-level validation.
References#
- CVE-2025-5276: SSRF in markdownify-mcp
- Snyk Labs: “Prompt Injection Meets MCP” (July 2025)
- OWASP SSRF Prevention Cheat Sheet