iOfficeAI/OfficeCLI · error · ArgumentException
Remote image exceeds {SsrfGuard.MaxRemoteBytes / (1024 * 102
Error message
Remote image exceeds {SsrfGuard.MaxRemoteBytes / (1024 * 1024)} MB limit. What it means
Thrown by ImageSource.ResolveUrl when a remote image download exceeds the shared size cap defined in SsrfGuard.MaxRemoteBytes (100 MB). The check fires in two places: first against the Content-Length response header (if the server declares it), and second during streaming via SsrfGuard.ReadBounded which enforces the cap even when Content-Length is absent. The limit is shared between image fetch and file fetch so policy cannot diverge.
Source
Thrown at src/officecli/Core/ImageSource.cs:164
private static (Stream, PartTypeInfo) ResolveUrl(string url)
{
// SSRF guard lives in the shared SsrfGuard so image and file fetch can
// never diverge in policy. See SsrfGuard for the connect-time / redirect
// / DNS-rebinding rationale.
var handler = SsrfGuard.CreateGuardedHandler("image");
using var client = new HttpClient(handler, disposeHandler: true) { Timeout = TimeSpan.FromSeconds(30) };
client.DefaultRequestHeaders.Add("User-Agent", "OfficeCLI");
var response = client.GetAsync(url).GetAwaiter().GetResult();
response.EnsureSuccessStatusCode();
// Enforce the shared size cap whether or not the server sends
// Content-Length. ReadBounded lives in SsrfGuard so image and file
// fetch share one limit (see SsrfGuard.MaxRemoteBytes).
var declared = response.Content.Headers.ContentLength;
if (declared is > SsrfGuard.MaxRemoteBytes)
throw new ArgumentException($"Remote image exceeds {SsrfGuard.MaxRemoteBytes / (1024 * 1024)} MB limit.");
var bytes = SsrfGuard.ReadBounded(response.Content.ReadAsStream(), SsrfGuard.MaxRemoteBytes, url, "image");
var stream = new MemoryStream(bytes);
// Try content-type header first
var serverMime = response.Content.Headers.ContentType?.MediaType;
if (!string.IsNullOrEmpty(serverMime) && TryMimeToContentType(serverMime, out var ct))
return (stream, ct);
// Fallback: extract extension from URL path (strip query string)
var uri = new Uri(url);
var ext = Path.GetExtension(uri.AbsolutePath);
if (!string.IsNullOrEmpty(ext))
return (stream, ExtensionToContentType(ext));
// Last resort: sniff magic bytes
if (TrySniffContentType(bytes, out var sniffed))
return (stream, sniffed);
View on GitHub (pinned to 1ced45e900)
Solutions
- Download the image locally, resize/compress it to under 100 MB, and embed the local file instead.
- Use a URL that points to a smaller version or thumbnail of the image.
- If the limit is genuinely too low for your use case, host a pre-resized image at a different URL.
Example fix
// before — remote image too large add image src='https://example.com/huge-tiff-200mb.tif' path='/body' // after — download, compress, embed locally // wget -O /tmp/img.tif 'https://example.com/huge-tiff-200mb.tif' // magick /tmp/img.tif -resize 50% -compress LZW /tmp/img-small.tif add image src='/tmp/img-small.tif' path='/body'
Defensive patterns
Strategy: validation
Validate before calling
// Pre-check: HEAD the URL to get Content-Length before full download
using var client = new HttpClient();
var headResp = await client.SendAsync(new HttpRequestMessage(HttpMethod.Head, url));
if (headResp.Content.Headers.ContentLength is long len && len > SsrfGuard.MaxRemoteBytes)
{
Console.Error.WriteLine($"Remote image is {len / (1024*1024)} MB, exceeds the {SsrfGuard.MaxRemoteBytes / (1024*1024)} MB limit.");
return;
} Try / catch
try
{
var (stream, contentType) = ImageSource.Resolve(url);
}
catch (ArgumentException ex) when (ex.Message.Contains("MB limit"))
{
// Download locally, compress/resize, embed as local file
} Prevention
- Pre-check the image size with a HEAD request before embedding from a URL.
- Compress or resize large images before embedding them into Office documents.
- Prefer local file embedding for images larger than a few MB to avoid network-related failures.
When it happens
Trigger: Calling ImageSource.Resolve with an HTTP(S) URL pointing to an image larger than 100 MB. The declared Content-Length header value exceeds MaxRemoteBytes, or the streamed bytes exceed the cap during ReadBounded. The SSRF guard handler wraps the HttpClient for DNS-rebinding and redirect protection, and the size cap is enforced on top.
Common situations: Linking to a high-resolution stock photo or satellite imagery that exceeds 100 MB. A URL that redirects to a much larger payload than expected. A misconfigured server returning an incorrect Content-Length or no Content-Length with a very large body.
Related errors
- Remote file exceeds {SsrfGuard.MaxRemoteBytes / (1024 * 1024
- Cannot determine image type from URL: {url}. Specify format
- Refusing to fetch {what} from non-public address '{addr}' (h
- Checksum mismatch for ${asset} (expected ${expected}, got ${
- Could not download OfficeCLI binary (${asset} @ ${TAG}). Las
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/abbb1535007d9de8.
Report an issue: GitHub.