iOfficeAI/OfficeCLI · error · ArgumentException
Remote file exceeds {SsrfGuard.MaxRemoteBytes / (1024 * 1024
Error message
Remote file exceeds {SsrfGuard.MaxRemoteBytes / (1024 * 1024)} MB limit. What it means
Thrown by FileSource.ResolveUrl when a remote file's declared Content-Length exceeds the 100 MB cap (SsrfGuard.MaxRemoteBytes). The fetch uses an SSRF-guarded handler and bounds memory by both the declared length and a bounded read of the actual stream, so an oversized or lying response is rejected.
Source
Thrown at src/officecli/Core/FileSource.cs:109
{
// SSRF guard: same connect-time public-IP enforcement as image fetch —
// refuse loopback / private / link-local / cloud-metadata targets. See
// SsrfGuard. Without this, a caller-supplied data=/model3d=/media= URL
// is an SSRF primitive when officecli runs on untrusted input.
var handler = SsrfGuard.CreateGuardedHandler("file");
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();
// Bound memory use: fail fast on an honest oversized Content-Length, then
// read through the shared SsrfGuard.ReadBounded so a chunked / lying
// response can't exhaust memory either. Same cap as the image path.
var declared = response.Content.Headers.ContentLength;
if (declared is > SsrfGuard.MaxRemoteBytes)
throw new ArgumentException(
$"Remote file exceeds {SsrfGuard.MaxRemoteBytes / (1024 * 1024)} MB limit.");
var bytes = SsrfGuard.ReadBounded(
response.Content.ReadAsStream(), SsrfGuard.MaxRemoteBytes, url, "file");
// Try extension from URL path
var uri = new Uri(url);
var ext = Path.GetExtension(uri.AbsolutePath).ToLowerInvariant();
// Fallback: infer from content-type header
if (string.IsNullOrEmpty(ext))
{
var mime = response.Content.Headers.ContentType?.MediaType;
ext = MimeToExtension(mime);
}
return (new MemoryStream(bytes), ext);
}
View on GitHub (pinned to 1ced45e900)
Solutions
- Use a smaller asset, or compress/resize it below 100 MB before referencing it.
- Host the large file locally and pass a filesystem path instead of a URL.
- Confirm the URL resolves to the intended (small) file and isn't redirecting to a larger resource.
Example fix
// before
var (stream, ext) = FileSource.Resolve("https://cdn.example.com/huge_video.mp4");
// after
var (stream, ext) = FileSource.Resolve("./local/small_clip.mp4"); Defensive patterns
Strategy: validation
Validate before calling
static async Task<long> HeadContentLengthAsync(string url)
{
using var h = SsrfGuard.CreateGuardedHandler("file");
using var c = new HttpClient(h) { Timeout = TimeSpan.FromSeconds(30) };
var resp = await c.SendAsync(new HttpRequestMessage(HttpMethod.Head, url));
return resp.Content.Headers.ContentLength ?? -1;
} Try / catch
try { var r = FileSource.Resolve(url); }
catch (ArgumentException ex) when (ex.Message.Contains("MB limit"))
{ /* use a smaller/local asset */ } Prevention
- Keep remote assets under 100 MB.
- HEAD the URL first to check Content-Length before fetching.
When it happens
Trigger: Calling FileSource.Resolve (or a media/image/model3d fetch) with an http(s):// URL whose response Content-Length is greater than 100 MB (100 * 1024 * 1024 bytes). The check runs after a successful HTTP response but before reading the body.
Common situations: Pointing at a large asset (video, hi-res image, big model); a URL that returns a download/redirect to a much larger file; a misconfigured asset server.
Related errors
- Remote image exceeds {SsrfGuard.MaxRemoteBytes / (1024 * 102
- 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
- officecli install failed. Run manually: irm ${INSTALL_PS
AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13).
Data as JSON: /api/errors/ebcacf8a125d2c18.
Report an issue: GitHub.