SSRFGuard Security in OfficeCLI for External Resources: Connect-Time Validation Architecture
OfficeCLI centralizes SSRF protection in SsrfGuard.cs, validating IP addresses at socket connection time to block private networks while enforcing a 100 MB cap on all remote resource fetches.
OfficeCLI enables embedding of remote assets—images, 3D models, and documents—via URLs that may originate from untrusted user input. To mitigate Server-Side Request Forgery (SSRF) risks against internal infrastructure and cloud metadata services, the tool implements robust SSRFGuard security in OfficeCLI for external resources through a low-level network validation layer.
How the SSRF Guard Validates Connections
Connect-Time IP Filtering
At the core of the defense is SsrfGuard.CreateGuardedHandler(string what), defined in src/officecli/Core/SsrfGuard.cs (lines 36‑66). This method returns a SocketsHttpHandler configured with a custom ConnectCallback that intercepts every TCP connection attempt.
The callback resolves the target hostname to its constituent IP addresses and validates each against a whitelist of publicly routable ranges before allowing the socket to open. This connect-time validation eliminates DNS rebinding windows by inspecting the actual IP address used for the transport, not just the DNS response.
Blocked Address Ranges
The IsPublicAddress(IPAddress address) method (lines 10‑39) implements the security policy by rejecting:
- 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 networks including cloud-metadata endpoints (169.254.0.0/16)
- CGNAT space (100.64.0.0/10)
- Multicast ranges
- IPv6 unique-local addresses
If any resolved IP falls within these ranges, the ConnectCallback throws an ArgumentException with a descriptive security message, terminating the request before data transmission begins.
Size Limiting and Bounded Reads
To prevent memory exhaustion from maliciously large payloads, the guard enforces a uniform MaxRemoteBytes = 100 MB limit across all fetchers. The ReadBounded method (lines 81‑103) wraps response streams and aborts reads immediately when the cumulative byte count exceeds this threshold, protecting against both honest large files and crafted chunked responses.
Integration with External Resource Fetchers
ImageSource Implementation
The ImageSource.ResolveUrl method (lines 42‑60 in src/officecli/Core/ImageSource.cs) instantiates a guarded handler via CreateGuardedHandler("image") before executing the HTTP request. This ensures that every image fetch—whether from HTTPS URLs or data-URIs—undergoes the same IP validation and size constraints.
FileSource Implementation
Similarly, FileSource.ResolveUrl (lines 74‑96 in src/officecli/Core/FileSource.cs) applies CreateGuardedHandler("file") to generic file downloads including GLB models and document attachments. Both fetchers utilize ReadBounded to stream content into memory-safe buffers, ensuring consistent SSRFGuard security in OfficeCLI for external resources regardless of asset type.
Practical Usage Examples
Fetching Images Safely
When resolving remote images, the guard automatically validates the endpoint:
// Returns a stream and the appropriate OpenXml image part type.
// Throws if the URL resolves to a private address or exceeds 100 MB.
var (stream, partType) = ImageSource.Resolve("https://example.com/logo.png");
Fetching Generic Files
For 3D models or other binary assets:
// Returns a seekable MemoryStream and inferred file extension.
// SSRF guard blocks private/internal URLs and caps the download size.
var (stream, ext) = FileSource.Resolve("https://assets.example.com/model.glb");
// ext will be ".glb" if the server supplies a matching Content-Type header.
Direct Guard Utilization
For advanced scenarios requiring custom HTTP clients:
var handler = SsrfGuard.CreateGuardedHandler("custom");
using var client = new HttpClient(handler) { Timeout = TimeSpan.FromSeconds(30) };
var resp = await client.GetAsync("https://public-api.example.org/data");
var data = SsrfGuard.ReadBounded(await resp.Content.ReadAsStreamAsync(),
SsrfGuard.MaxRemoteBytes,
"https://public-api.example.org/data",
"custom");
Summary
- Connect-time validation in
SsrfGuard.csinspects actual socket IPs, preventing DNS rebinding attacks against internal services. - Comprehensive range blocking covers RFC 1918, link-local (including 169.254.0.0/16), and multicast addresses via
IsPublicAddress. - Uniform size enforcement via
ReadBoundedandMaxRemoteByteslimits all remote fetches to 100 MB, preventing memory exhaustion. - Centralized architecture ensures
ImageSourceandFileSourceshare identical security postures throughCreateGuardedHandler. - Redirect safety maintains protection across up to 10 hops, with each intermediate address undergoing public-range verification.
Frequently Asked Questions
How does OfficeCLI prevent DNS rebinding attacks?
OfficeCLI validates IP addresses at socket connection time rather than DNS resolution time. The ConnectCallback in CreateGuardedHandler resolves the hostname and inspects every candidate IP against IsPublicAddress immediately before establishing the TCP connection. This ensures that even if DNS returns different addresses during resolution versus connection, the actual transport endpoint is vetted.
What specific IP ranges does the SSRF guard block?
According to the source code in src/officecli/Core/SsrfGuard.cs, the IsPublicAddress method blocks loopback (127.0.0.0/8), private RFC 1918 networks (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), link-local addresses including AWS/Azure metadata endpoints (169.254.0.0/16), CGNAT (100.64.0.0/10), multicast ranges, and IPv6 unique-local addresses.
Can developers configure the maximum download size limit?
Currently, the MaxRemoteBytes constant is hardcoded to 100 MB in SsrfGuard.cs. While the ReadBounded method accepts this as a parameter, both ImageSource and FileSource utilize the static MaxRemoteBytes value, meaning all external resource fetches share this uniform cap without runtime configuration options.
Does the SSRF guard restrict HTTP redirects?
The guard allows up to 10 redirect hops to support public CDNs, but each redirect target undergoes identical scrutiny. Every intermediate URL is resolved and its IP addresses validated through IsPublicAddress during the connection phase, ensuring that redirect chains cannot bypass private network 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →