# How OfficeCLI SsrfGuard Protects Against SSRF Attacks in Operations

> OfficeCLI SsrfGuard stops SSRF attacks by validating public IPs, blocking private networks and cloud metadata, ensuring redirect safety and enforcing size limits.

- Repository: [OfficeAI/OfficeCLI](https://github.com/iofficeai/OfficeCLI)
- Tags: how-to-guide
- Published: 2026-07-31

---

**OfficeCLI SsrfGuard prevents Server-Side Request Forgery (SSRF) by enforcing connect-time public-IP validation on every HTTP request, blocking private network addresses, link-local ranges, and cloud metadata endpoints while maintaining redirect safety and enforcing a 100 MB response size limit.**

Every remote fetch operation in iOfficeAI/OfficeCLI—whether loading images, files, models, or media—routes through a centralized security layer called `SsrfGuard`. This shared component ensures that malicious URLs cannot probe internal networks or cloud metadata services, providing uniform protection across all CLI operations that interact with external resources.

## Connect-Time IP Validation: The Core Defense

The primary defense mechanism resides in `SsrfGuard.CreateGuardedHandler`, implemented in [`src/officecli/Core/SsrfGuard.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/Core/SsrfGuard.cs) at lines 26-53. This method constructs a `SocketsHttpHandler` with a custom `ConnectCallback` that intercepts TCP connections **after** DNS resolution but **before** the socket opens.

When a connection attempt begins, the callback enumerates **all** IP addresses returned by DNS resolution and validates each through `IsPublicAddress`. Any address matching the following criteria triggers an immediate `ArgumentException`:

- **Loopback addresses** (127.0.0.0/8, ::1)
- **Private RFC-1918 ranges** (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
- **Link-local addresses** (169.254.0.0/16), including cloud metadata endpoints
- **CGNAT ranges**, multicast addresses, or unspecified addresses

This connect-time validation eliminates DNS-rebinding and Time-of-Check-Time-of-Use (TOCTOU) vulnerabilities because the guard inspects the actual socket address rather than relying solely on the hostname string.

## Redirect-Aware Enforcement

Legitimate operations often require following redirects to content delivery networks. Rather than disabling automatic redirects, `SsrfGuard` sets `AllowAutoRedirect = true` while ensuring every redirect hop re-enters the same `ConnectCallback` validation pipeline.

This architectural choice guarantees that an attacker cannot bypass IP restrictions by redirecting from a public endpoint to an internal service. Each intermediate URL undergoes identical DNS resolution and address vetting before any TCP connection establishes.

## Memory Safety Through Response Size Limits

Beyond network-level protection, `SsrfGuard` enforces a hard ceiling on remote payload sizes to prevent memory-exhaustion attacks. The class defines `MaxRemoteBytes` as 100 MiB (104,857,600 bytes), implemented in [`src/officecli/Core/SsrfGuard.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/Core/SsrfGuard.cs) at lines 71-84.

After a request succeeds, callers consume the response body through `SsrfGuard.ReadBounded`, which streams data continuously and aborts immediately upon exceeding the byte limit. This protection remains effective even when remote servers lie about `Content-Length` headers, as the enforcement occurs during actual byte consumption rather than header inspection.

## Centralized Policy Architecture

Both image fetching and generic file downloading utilize the same guard instance, ensuring consistent policy enforcement. In [`src/officecli/Core/ImageSource.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/Core/ImageSource.cs) (lines 48-66), the `ResolveUrl` method instantiates the guard via `SsrfGuard.CreateGuardedHandler("image")`. Similarly, [`src/officecli/Core/FileSource.cs`](https://github.com/iOfficeAI/OfficeCLI/blob/main/src/officecli/Core/FileSource.cs) (lines 92-112) invokes the same method with the context string `"file"`.

This centralized approach prevents security drift between different resource types. Whether fetching a PNG logo or a dataset CSV, the identical validation logic applies:

1. **URL Detection** – `ImageSource.Resolve` or `FileSource.Resolve` identifies `http(s)://` schemes
2. **Guard Creation** – Handler instantiation with custom `ConnectCallback`
3. **DNS & Vetting** – Resolution and `IsPublicAddress` validation
4. **Connection** – TCP socket creation only for public addresses
5. **Redirect Handling** – Automatic hops re-enter validation
6. **Size Enforcement** – `ReadBounded` streaming with 100 MiB cap

## Practical Usage Examples

The following examples demonstrate the guard's behavior in common scenarios:

```csharp
// Valid public image fetch (succeeds)
var (stream, contentType) = ImageSource.Resolve(
    "https://cdn.example.com/logo.png");

// Private network access attempt (throws ArgumentException)
try
{
    var result = ImageSource.Resolve("http://192.168.1.10/secret.png");
}
catch (ArgumentException ex)
{
    // Output: Refusing to fetch image from non-public address...
    Console.WriteLine(ex.Message);
}

// Oversized file attempt (throws ArgumentException)
try
{
    var (fileStream, ext) = FileSource.Resolve(
        "https://large.example.com/big-video.mp4");
}
catch (ArgumentException ex)
{
    // Output: Remote file exceeds 100 MB limit.
    Console.WriteLine(ex.Message);
}

```

Each high-level `Resolve` call automatically executes the complete guard pipeline, allowing developers to fetch remote resources without manually implementing SSRF protections.

## Summary

- **Connect-time validation** in `SsrfGuard.CreateGuardedHandler` blocks private and link-local IP addresses at the socket level, preventing DNS-rebinding attacks.
- **Redirect safety** ensures every hop in a redirect chain undergoes identical IP vetting through the persistent `ConnectCallback`.
- **Memory protection** via `MaxRemoteBytes` and `ReadBounded` enforces a 100 MiB ceiling on all remote responses, regardless of header manipulation.
- **Centralized policy** across `ImageSource` and `FileSource` guarantees uniform SSRF defenses without code duplication or configuration drift.
- **Zero-trust architecture** treats all external URLs as untrusted, with no baked-in whitelists that could introduce bypass vulnerabilities.

## Frequently Asked Questions

### What types of IP addresses does SsrfGuard block?

SsrfGuard blocks loopback addresses (127.0.0.0/8, ::1), private RFC-1918 ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), link-local addresses including the 169.254.0.0/16 cloud-metadata range, CGNAT ranges, multicast addresses, and unspecified addresses. Any connection attempt resolving to these ranges throws an `ArgumentException` before TCP handshake completes.

### How does SsrfGuard prevent DNS rebinding attacks?

Traditional SSRF protections often resolve hostnames to IPs once, then connect later, creating a TOCTOU window where DNS responses change between check and use. SsrfGuard's `ConnectCallback` resolves hostnames **during** the connection attempt and validates the actual socket address immediately before opening the TCP connection, eliminating the race condition that DNS rebinding exploits.

### Can attackers bypass protection using HTTP redirects?

No. While `AllowAutoRedirect` remains enabled to support legitimate CDNs, every redirect target re-enters the same `ConnectCallback` validation pipeline. If a redirect points to a private IP address or blocked range, the connection aborts with the same `ArgumentException` as a direct request, ensuring no bypass through intermediate public endpoints.

### What happens when a remote file exceeds the size limit?

When a response stream exceeds `SsrfGuard.MaxRemoteBytes` (100 MiB), the `ReadBounded` method aborts the operation and throws an `ArgumentException` with the message "Remote file exceeds 100 MB limit." This occurs during actual byte streaming rather than header inspection, protecting against servers that provide fraudulent `Content-Length` values.