SSRF Protection
How NIN Connect prevents Server-Side Request Forgery attacks in the tool execution proxy.
Overview
The tool executor acts as a server-side proxy. It takes a plugin's baseUrl, appends the tool's path, and calls fetch() on behalf of the user. Without protection, an admin who configures a malicious baseUrl (or an attacker who gains admin access) could direct the server to fetch internal resources like cloud metadata endpoints, database ports, or other services on the private network.
How It Works
Before every outbound HTTP request in the tool executor, the URL passes through validateUrlForFetch() in lib/security/url-validator.ts:
1. Protocol Check
Only http: and https: protocols are allowed. Anything else (file:, ftp:, data:, javascript:) is rejected immediately.
2. Hostname Check
If the hostname is a raw IP address, it is checked against the private range blocklist before any network call is made.
3. DNS Resolution
The hostname is resolved via dns.resolve4() and dns.resolve6(). Every resolved IP address is checked against the blocklist. If any resolved IP is private, the request is blocked.
This prevents DNS rebinding attacks where a hostname initially resolves to a public IP but later resolves to a private one.
4. Private IP Ranges
The following ranges are blocked:
| Range | Description |
|---|---|
127.0.0.0/8 | Loopback |
10.0.0.0/8 | RFC 1918 private |
172.16.0.0/12 | RFC 1918 private |
192.168.0.0/16 | RFC 1918 private |
169.254.0.0/16 | Link-local (cloud metadata) |
0.0.0.0/8 | "This" network |
::1 | IPv6 loopback |
fc00::/7 | IPv6 unique local |
fe80::/10 | IPv6 link-local |
Integration Point
The check runs in lib/proxy/executor.ts at the executeManualRoute function, immediately after the final URL is constructed and before fetch() is called:
const url = `${plugin.baseUrl}${path}`;
// SSRF protection — validate before fetching
await validateUrlForFetch(url);
const response = await fetch(url, fetchOpts);If validation fails, the tool execution returns an error response without making any network request.
What This Protects Against
- Cloud metadata theft —
http://169.254.169.254/latest/meta-data/on AWS/GCP - Internal service scanning —
http://localhost:5432,http://10.0.0.1:6379 - DNS rebinding — hostname that resolves to
127.0.0.1after initial check - Protocol smuggling —
file:///etc/passwd,ftp://internal-host
Limitations
- The DNS resolution check happens at validation time. In theory, DNS could change between validation and fetch. This is a known limitation of all DNS-based SSRF defenses. For higher assurance, use network-level controls (firewall rules, VPC policies) in addition to application-level checks.
- MCP tool execution connects to remote MCP servers directly and is not currently routed through this validator. MCP server URLs should be vetted during admin setup.