Security Considerations
Image processing is powerful, but it is also one of the easier places for an application to burn CPU, memory, and time on untrusted input. This page is written as a practical hardening guide: what to check early, what to limit, and which ImageSharp hooks help you keep risky inputs under control.
Preflight with Identify When Possible
If you only need to validate dimensions, frame count, metadata presence, or pixel information, use Image.Identify() instead of a full decode.
using SixLabors.ImageSharp;
ImageInfo info = Image.Identify("upload.bin");
Console.WriteLine($"{info.Width}x{info.Height}");
Console.WriteLine($"Frames: {info.FrameCount}");
Console.WriteLine($"Bits per pixel: {info.PixelType.BitsPerPixel}");
Console.WriteLine($"Estimated pixel memory: {info.GetPixelMemorySize():N0} bytes");
This lets you reject obviously unsuitable files before allocating the full decoded image buffers.
ImageInfo.GetPixelMemorySize() is particularly useful here. It gives you a decoded pixel-memory estimate up front, which helps protect services against inputs that are cheap to upload but expensive to expand into memory, especially when many frames are involved.
Reduce Decode Cost with DecoderOptions
DecoderOptions is the main place to constrain decode behavior:
TargetSizedecodes to a bounded fit-within size equivalent toResizeMode.Max.MaxFrameslimits how many frames are decoded from animated formats.SkipMetadataavoids loading encoded metadata when you do not need it.SegmentIntegrityHandlingcontrols how tolerant decoding is of damaged segments.
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats;
DecoderOptions options = new()
{
MaxFrames = 1,
SkipMetadata = true,
TargetSize = new Size(1600, 1600),
SegmentIntegrityHandling = SegmentIntegrityHandling.Strict
};
using Image image = Image.Load(options, stream);
For public upload endpoints, MaxFrames = 1 is often appropriate when you only need a poster frame or preview. Likewise, SkipMetadata = true is a straightforward win when EXIF, ICC, IPTC, and XMP data are irrelevant to the workflow.
Be Deliberate About Error Tolerance
SegmentIntegrityHandling is a tradeoff between strictness and recovery:
Strictrejects files on any recoverable segment validation error.IgnoreAncillaryis the library default and ignores recoverable errors in optional metadata or other ancillary segments.IgnoreImageDataalso ignores recoverable image data segment errors and is better suited to recovery tools than to public-facing ingest paths.
That recommendation is an inference from the enum semantics: the more errors you ignore, the more "best effort" your decode path becomes.
Restrict the Supported Format Set
If your service only needs a small number of formats, build a dedicated Configuration instead of exposing every registered codec:
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Png;
Configuration config = new(
new PngConfigurationModule(),
new JpegConfigurationModule());
DecoderOptions options = new()
{
Configuration = config
};
This reduces the amount of format detection and decoder surface area involved in that pipeline.
Limit Memory Use
You can impose conservative allocation limits with a custom MemoryAllocator:
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Memory;
Configuration config = Configuration.Default.Clone();
config.MemoryAllocator = MemoryAllocator.Create(new MemoryAllocatorOptions
{
// Roughly limits the workload to about 64 megapixels of Rgba32 data.
AllocationLimitMegabytes = 256,
// Limits the combined size of all active allocations made through this allocator.
AccumulativeAllocationLimitMegabytes = 512
});
AllocationLimitMegabytes limits the size of any one live allocation group. When it is unset, ImageSharp uses the platform default: 1 GB on 32-bit processes and 4 GB on 64-bit processes. AccumulativeAllocationLimitMegabytes limits the combined size of all active allocations made through the allocator instance. It is unset by default, which means there is no accumulative cap unless you configure one. Use both limits together when a service can process several images or several intermediate buffers at the same time.
This is one of the most important safeguards for services that handle arbitrary uploads. For broader guidance on allocator behavior and tradeoffs, see Memory Management.
Put Outer Limits Around Streams and Requests
ImageSharp requires a readable stream, and for non-seekable streams it copies the input into an internal seekable memory stream before decoding. In practice that means request-body limits, upload-size limits, and outer buffering rules still matter even before pixel buffers are allocated.
Use your hosting layer to enforce:
- maximum request body size;
- authentication or signed commands when appropriate;
- rate limiting;
- reverse proxy limits; and
- service or container isolation for expensive workloads.
For ImageSharp.Web command signing, see Securing Requests in ImageSharp.Web.
Practical Security Defaults
- Use
Identify()first whenever a full decode is not necessary. - Use
GetPixelMemorySize()during identify-based preflight when you need a decoded memory budget check. - Use
TargetSize,MaxFrames, andSkipMetadatato shrink decode cost up front. - Prefer
Strictor the defaultIgnoreAncillaryover broader error ignoring on untrusted inputs. - Restrict the enabled format modules when your workload only needs a few codecs.
- Use per-allocation, accumulative allocator, and host-level request limits together rather than relying on only one layer.