How to Prevent SSRF Vulnerabilities in Agent-Native Using ssrfSafeFetch

TLDR: Agent-Native's ssrfSafeFetch helper prevents Server-Side Request Forgery attacks by implementing four layers of validation—static URL parsing, DNS-aware runtime checks, connect-time IP filtering, and manual redirect inspection—before executing any server-side request.

Agent-Native safeguards every server-side request that receives a URL from users, agents, or external sources by routing it through the centralized ssrfSafeFetch utility. This helper, located in packages/core/src/extensions/url-safety.ts, implements a defense-in-depth strategy against Server-Side Request Forgery (SSRF) that blocks both literal private network requests and sophisticated DNS rebinding attacks. By importing this single function from @agent-native/core/extensions/url-safety, developers ensure their agent actions inherit robust protection without implementing complex validation logic manually.

Understanding the ssrfSafeFetch Security Layers

The ssrfSafeFetch function orchestrates multiple validation stages to eliminate SSRF attack vectors. According to the BuilderIO/agent-native source code, each layer addresses a specific vulnerability window in the request lifecycle.

Static URL Validation with isBlockedExtensionUrl

Before any network activity occurs, ssrfSafeFetch invokes isBlockedExtensionUrl to parse and reject dangerous URLs based on their literal values. As implemented in lines 94-108 of packages/core/src/extensions/url-safety.ts, this function blocks:

  • Non-HTTP/HTTPS schemes (eliminating file://, gopher://, and other protocol handlers)
  • Hostnames resolving to known private addresses (localhost, ::1, 127.0.0.1, etc.)
  • Domains listed in METADATA_HOSTS (cloud metadata services)
  • Hostnames ending with DNS-rebinding suffixes such as .nip.io or .xip.io

This static validation prevents obvious attacks where attackers supply literal internal IP addresses or known bypass domains.

DNS-Aware Runtime Verification

To catch attacks where a public hostname resolves to a private IP after validation, ssrfSafeFetch employs isBlockedExtensionUrlWithDns. This function first runs the static check, then resolves the hostname using node:dns/promises as shown in lines 27-48 of packages/core/src/extensions/url-safety.ts.

If any resolved IP address belongs to a private range (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, etc.), the request aborts immediately. This layer specifically targets DNS rebinding attacks where adversaries control DNS records that flip between public and private IPs.

Connect-Time Protection with createSsrfSafeDispatcher

Even after DNS validation, a Time-of-Check to Time-of-Use (TOCTOU) window exists where the DNS record could change before the TCP connection establishes. To eliminate this race condition, Agent-Native uses createSsrfSafeDispatcher to build a custom Undici Agent that performs its own DNS lookup immediately before the TCP connection.

As implemented in lines 51-62 and the lookup callback in lines 89-108 of packages/core/src/extensions/url-safety.ts, this dispatcher aborts the connection if the resolved IP is private. This connect-time verification ensures that even if the DNS record changes between the initial check and the actual socket connection, the request cannot reach internal networks.

Manual Redirect Handling

Automatic redirects present another SSRF vector where a public URL redirects to a private internal address. The ssrfSafeFetch function disables automatic redirects by setting redirect: "manual" and caps the total number of hops using maxRedirects (defaulting to 3).

As shown in lines 60-78 of packages/core/src/extensions/url-safety.ts, each redirect hop undergoes the same DNS-aware validation sequence before following the next URL. This prevents attackers from using 30x redirects to pivot from public endpoints into private infrastructure.

Implementing ssrfSafeFetch in Server Actions

All server-side code that fetches external resources should import ssrfSafeFetch from @agent-native/core/extensions/url-safety. The helper abstracts the protection layers, presenting a standard fetch-like API.

Basic Usage Pattern

import { ssrfSafeFetch } from "@agent-native/core/extensions/url-safety";

export async function fetchPublicJson(url: string) {
  // Automatically vets for private hosts and DNS rebinding
  const response = await ssrfSafeFetch(
    url,
    {
      headers: { "Accept": "application/json" },
      signal: AbortSignal.timeout(5000),
    },
    { maxRedirects: 2 }
  );

  if (!response.ok) {
    throw new Error(`Failed: ${response.status}`);
  }
  return response.json();
}

Real-World Implementation Example

The analyze-brand-assets.ts template demonstrates production usage:

const url = normalizeBrandWebsiteUrl(websiteUrl);
const response = await ssrfSafeFetch(
  url,
  {
    headers: {
      "User-Agent":
        "Mozilla/5.0 (compatible; AgentNative/1.0; +https://agent-native.com)",
    },
    signal: AbortSignal.timeout(10_000),
  },
  { maxRedirects: 3 },
);
const html = await response.text();

This pattern appears throughout the codebase, including in packages/core/src/file-upload/actions/upload-image.ts and packages/core/src/notifications/channels.ts, ensuring consistent protection across image processing and notification delivery paths.

Advanced: Custom Dispatcher Configuration

While rarely necessary, you can create a standalone SSRF-safe dispatcher for use with other fetch implementations:

import { createSsrfSafeDispatcher } from "@agent-native/core/extensions/url-safety";

const dispatcher = await createSsrfSafeDispatcher();
if (dispatcher) {
  await fetch("https://example.com", { dispatcher });
}

Validating SSRF Protections

The test suite in packages/core/src/extensions/ssrf-fetch.spec.ts verifies protection against private hosts, DNS rebinding scenarios, and malicious redirect chains. When extending Agent-Native, reference these tests to ensure your implementations maintain the security guarantees of the core framework.

Summary

  • Multi-layered validation: ssrfSafeFetch combines static parsing, DNS resolution checks, and connect-time IP filtering to eliminate SSRF vectors.
  • DNS rebinding protection: The helper validates IPs both before and during connection establishment, blocking attacks that switch DNS records between public and private addresses.
  • Redirect safety: Manual redirect handling with re-validation prevents attackers from using intermediary public URLs to reach private networks.
  • Simple integration: Import ssrfSafeFetch from @agent-native/core/extensions/url-safety to automatically apply protection to any server-side fetch operation.
  • Implementation location: Core logic resides in packages/core/src/extensions/url-safety.ts with usage examples in templates/videos/actions/analyze-brand-assets.ts.

Frequently Asked Questions

How does Agent-Native prevent DNS rebinding attacks specifically?

Agent-Native prevents DNS rebinding through redundant IP validation at two distinct phases. First, isBlockedExtensionUrlWithDns resolves the hostname and checks for private ranges before initiating the request. Second, createSsrfSafeDispatcher performs a fresh DNS lookup immediately before the TCP connection via a custom Undici lookup callback. This dual verification ensures that even if an attacker changes the DNS record between validation and connection, the request aborts when the socket attempts to connect to a private IP.

Can I increase the redirect limit for ssrfSafeFetch?

Yes, the third argument to ssrfSafeFetch accepts an options object where you can specify maxRedirects. While the default is 3 to prevent infinite loops and redirect chains, you can increase this value for legitimate use cases requiring multiple hops. Each redirect undergoes the same SSRF validation sequence regardless of the limit set.

Does ssrfSafeFetch support protocols other than HTTP and HTTPS?

No, ssrfSafeFetch explicitly blocks non-HTTP/HTTPS schemes at the static validation layer via isBlockedExtensionUrl. This restriction prevents protocol-related attacks such as file:// access to local filesystems or gopher:// requests to internal services. The function is designed specifically for safe web resource fetching over standard HTTP protocols.

When should I use createSsrfSafeDispatcher instead of ssrfSafeFetch?

You should use createSsrfSafeDispatcher only when integrating with libraries that require a custom Undici Dispatcher instance rather than a standard fetch call. The ssrfSafeFetch helper already handles dispatcher creation internally, so direct usage of createSsrfSafeDispatcher is rare and typically reserved for advanced scenarios where you need fine-grained control over the HTTP agent configuration while maintaining SSRF protections.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →