How the SSRF Allowlist Protects Against Proxy-Side Request Forgery in Caveman
The SSRF allowlist in Caveman prevents proxy-side request forgery by validating all outbound URLs against a blocklist of unsafe addresses and an environment-driven allowlist, rejecting connections to internal networks unless explicitly permitted in self-hosted mode.
The JuliusBrussee/caveman repository implements a hardened defense against Server-Side Request Forgery (SSRF) attacks through its dedicated ssrf package in shared/platform/ssrf/ssrf.go. This system ensures that proxy-type providers—including Vertex, Bedrock, and GitHubApp integrations—cannot be exploited to access restricted internal services or private IP ranges. Understanding how the SSRF allowlist functions is essential for securing both managed multi-tenant deployments and self-hosted installations.
Core SSRF Protection Mechanisms
Blocklist Enforcement for Unsafe Destinations
At the foundation of the protection lies the ssrf.ValidateHost function, which automatically rejects connections to loopback addresses (127.0.0.0/8, ::1), link-local networks (169.254.0.0/16), and standard private ranges. When validation detects a forbidden destination, it returns specific errors such as "host … is blocked (loopback)" or "private address blocked in managed mode" before any TCP socket opens. This enforcement prevents attackers from using the proxy to scan local ports or access cloud metadata endpoints.
The Allowlist Override System
While the default policy denies access to internal addresses, the CAVE_SSRF_ALLOWLIST environment variable provides a controlled escape hatch parsed by the allowListSuggestion function. This allowlist accepts hostnames or host:port combinations that bypass blocklist restrictions. However, this override operates exclusively in self-hosted mode using ssrf.SelfHostedConfig. In managed mode, the system silently ignores the allowlist, ensuring that tenant workloads cannot circumvent network isolation to reach internal infrastructure.
Preventing Proxy-Side Request Forgery
The SSRF architecture counters proxy-side request forgery through a three-layer defense that inspects every outbound HTTP request:
-
Wrapped Network Dials: All outbound connections route through
ssrf.DialContext, utilized internally byssrf.NewHTTPClient. This interceptor validates destinations against both blocklists and allowlists before establishing any TCP connection, preventing low-level network bypasses. -
Mandatory URL Validation: Proxy providers must explicitly call
ssrf.ValidateURLbefore request construction. The Vertex provider implements this check inproxy/providers/vertex/routing.goat line 62, while the Bedrock provider applies identical validation inproxy/providers/bedrock/routing.goat line 202. This requirement ensures user-supplied URLs undergo security screening regardless of the provider type. -
Mode-Dependent Enforcement: The system distinguishes between
ssrf.SelfHostedConfigandssrf.ManagedConfig. Self-hosted operators can access local services—such as a private Ollama instance—by populating the allowlist. Managed deployments ignore the allowlist entirely, guaranteeing that malicious payloads cannot forge requests to internal databases or metadata services.
Implementation in Proxy Providers
Proxy providers integrate SSRF guards by invoking validation before HTTP client instantiation. The following pattern appears consistently across Vertex, Bedrock, and GitHubApp implementations:
func makeRequest(ctx context.Context, target *url.URL) (*http.Response, error) {
// Validate URL before any network activity
if err := ssrf.ValidateURL(ctx, target.String(), ssrf.ManagedConfig()); err != nil {
return nil, err
}
// Create client with enforced configuration
client := ssrf.NewHTTPClient(ssrf.ManagedConfig())
return client.Get(target.String())
}
This pattern ensures providers forwarding requests to external APIs cannot be hijacked to probe internal infrastructure. The GitHubApp provider applies the same validation in proxy/providers/githubapp/githubapp.go, demonstrating the universal application of these controls across all proxy implementations.
Configuring the SSRF Allowlist
Self-hosted deployments requiring access to internal services—such as locally-hosted language models—can configure explicit exemptions:
# Permit specific internal addresses
export CAVE_SSRF_ALLOWLIST="localhost,127.0.0.1:8080,192.168.1.50"
In Go code, instantiate the self-hosted configuration to respect these overrides:
// Initialize self-hosted config that reads CAVE_SSRF_ALLOWLIST
cfg := ssrf.SelfHostedConfig()
client := ssrf.NewHTTPClient(cfg)
// Request succeeds only if host is on allowlist
resp, err := client.Get("http://127.0.0.1:8080/health")
if err != nil {
// Handles: ssrf: destination 127.0.0.1:8080 is in blocked range
}
In managed mode, identical code using ssrf.ManagedConfig() would reject the same request regardless of environment variables, protecting shared infrastructure from tenant isolation breaches.
Summary
- The SSRF allowlist in Caveman blocks loopback, link-local, and private IP ranges by default through
ssrf.ValidateHostinshared/platform/ssrf/ssrf.go. - The
CAVE_SSRF_ALLOWLISTenvironment variable permits specific hosts only in self-hosted mode, while managed deployments ignore the allowlist to enforce strict tenant isolation. - Proxy providers such as Vertex and Bedrock must call
ssrf.ValidateURLbefore request construction, preventing forged requests from reaching internal networks. - The
ssrf.DialContextwrapper intercepts connections at the network layer, ensuring validation occurs before TCP handshakes complete.
Frequently Asked Questions
What is proxy-side request forgery?
Proxy-side request forgery occurs when an attacker manipulates a proxy server to make unauthorized requests to internal services or restricted networks that the attacker cannot access directly. In Caveman, this attack vector is mitigated by validating all outbound URLs against the SSRF blocklist before the proxy forwards any traffic, ensuring internal infrastructure remains unreachable.
Why does the allowlist only work in self-hosted mode?
The allowlist is restricted to self-hosted mode (ssrf.SelfHostedConfig) to prevent multi-tenant managed deployments from exposing internal infrastructure to tenant workloads. This design assumes self-hosted operators understand their specific network topology and intentionally expose services like local LLM endpoints, whereas managed mode requires absolute isolation between tenant code and system networks.
Which IP ranges are blocked by default?
Caveman's SSRF validator blocks loopback addresses (127.0.0.0/8 and ::1), link-local addresses (169.254.0.0/16), and standard private RFC1918 ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16). These restrictions are enforced in shared/platform/ssrf/ssrf.go and prevent unauthorized access to metadata services, local databases, and internal APIs.
How do proxy providers enforce SSRF validation?
Proxy providers enforce validation by calling ssrf.ValidateURL with the appropriate configuration before instantiating HTTP clients, as demonstrated in proxy/providers/vertex/routing.go and proxy/providers/bedrock/routing.go. They subsequently use ssrf.NewHTTPClient with either ssrf.ManagedConfig or ssrf.SelfHostedConfig, ensuring the underlying ssrf.DialContext wrapper rejects forbidden destinations at the connection level.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →