Table of Contents

Hardening untrusted input

A document from outside your organisation is untrusted input. It can be built to exhaust memory, disk or CPU: a ZIP bomb disguised as a .docx, a 100-megapixel image, tables nested thousands deep, a PDF that draws itself forever. ResourceLimits caps each of these, and a cap that trips throws a typed exception instead of taking down your process.

Set limits

using DocWright;
using DocWright.Core;

var options = new ConvertOptions();
options.Limits.MaxInputBytes = 50L * 1024 * 1024;            // refuse inputs over 50 MB
options.Limits.MaxOutputBytes = 200L * 1024 * 1024;
options.Limits.MaxPages = 2;                                 // tiny, to show a limit tripping
options.Limits.MaxImagePixels = 40_000_000;                  // about 40 megapixels per image
options.Limits.MaxUncompressedPartBytes = 200L * 1024 * 1024; // zip-bomb guards
options.Limits.MaxPackageCompressionRatio = 200.0;
options.Limits.MaxPackageEntryCount = 5000;
options.Limits.MaxNestedTableDepth = 50;
options.Limits.MaxApproximateMemoryBytes = 1L * 1024 * 1024 * 1024;
options.Limits.MaxWallClockTime = TimeSpan.FromSeconds(30);

try
{
    using FileStream input = File.OpenRead("quarterly-report.docx");   // three pages
    converter.Convert(input, Stream.Null, options);
}
catch (ResourceLimitExceededException ex)
{
    Console.WriteLine($"{ex.LimitName} exceeded (observed {ex.ObservedValue}): {ex.Message}");
}

Output

MaxPages exceeded (observed 3): The layout produced 3 pages, which exceeds MaxPages=2.

ResourceLimitExceededException.LimitName and ObservedValue say what tripped, so you can log it and tell the user.

Every limit

Limit Guards against Default
MaxInputBytes Huge uploads off
MaxOutputBytes Runaway output off
MaxPages Documents that lay out to thousands of pages off
MaxImagePixels Decompression bombs in images off
MaxUncompressedPartBytes ZIP bombs off
MaxPackageCompressionRatio ZIP bombs off
MaxPackageEntryCount Packages with millions of entries off
MaxNestedTableDepth Deeply nested tables off
MaxApproximateMemoryBytes Memory exhaustion off
MaxWallClockTime Slow documents off
MaxKeyDerivationSpinCount Encrypted files that demand millions of hash rounds 1,000,000
MaxPdfNestingDepth PDFs whose objects contain themselves 32
MaxPdfObjectCount PDFs declaring billions of objects 5,000,000
MaxPdfDecompressedBytes Compressed-stream bombs in PDFs, per stream 256 MB
MaxPdfContentOperations Endless drawing instructions, per page 20,000,000
MaxPdfFunctionSteps Expensive PDF functions, per evaluation 100,000

Set any limit to null to turn it off. The limits in bold are on by default, because their worst case doesn't depend on file size: a 200-byte PDF can recurse forever.

For a public upload endpoint, set at least MaxInputBytes, MaxWallClockTime, MaxPages and the two ZIP-bomb limits.

Limits that can't be turned off

Some failures are a StackOverflowException, which no catch can handle and which ends the process. The guards for those can be tightened but never removed:

  • MaxPdfNestingDepth: setting null, or anything above 1,000, still applies a 1,000-level ceiling.
  • The HTML, RTF and Markdown readers use iterative parsers with nesting limits (MaxNestingDepth: 256, 512 and 128), so hostile nesting throws a normal exception.
  • Report definitions, report expressions and report processing have their own limits, on by default. See Report expressions.

Also important

  • Nothing is fetched. No reader, field, template or merge ever makes a network or file request on a document's behalf. Server-side request forgery through a document isn't possible unless you plug in a resolver yourself.
  • Scripts are never run. HTML <script> is removed, report <Code> is never executed, and form-field macros are never run.
  • Cancellation. Pair MaxWallClockTime with a CancellationToken in ConvertAsync to stop work when the client goes away.
  • Isolation still helps. Limits bound DocWright's work, but running conversions in a separate worker process or container with its own memory cap is still good defence in depth for a public service.