CVE-2026-106118 is a high-severity (CVSS 7.5) Out-of-bounds Write vulnerability in ImageSharp. A fix is available for ImageSharp — see the affected versions and patch details below.
ImageSharp: Tiled fax TIFF: tile buffer sized by TileWidth but fax decompressor writes scanlines of ImageWidth — heap OOB write
Exploitation Status
No confirmed exploitation observed yet
- CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.
- CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.
Exploitation and automatability from CISA’s SSVC triage for CVE-2026-106118.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
How urgent is this, really
CVE-2026-106118 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.
Where this sits among everything scored
Of 394,415 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.
Real-World Exposure
ImageSharpReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects NuGet packages — download data is not available via public APIs for these ecosystems.
Description
Summary
When decoding a tiled TIFF with fax compression (T4/T6/MH), DecodeTilesChunky allocates each tile buffer from TileWidth (ceil(TileWidth*bpp/8)*TileLength bytes) but constructs the fax decompressor with frame.Width: TiffDecompressorsFactory ignores the isTiled/tileWidth/tileHeight parameters entirely. The T4/T6/MH decompressors treat the full image width as the scanline length and advance (and really write, via read-modify-write bit ops) frame.Width bits per row, with no bounds check against the tile buffer. The very first tile therefore writes linearly out of bounds — about ImageWidth/8 bytes per row × TileLength rows into a TileWidth-sized buffer. With ImageWidth=4,000,000, TileWidth=16, TileLength=16 this writes ~2 MB past a 32-byte buffer and kills the process deterministically; a T6 all-white variant advances the bit offset by >512 MB silently, showing an alarm-free heap-corruption window for the same defect. A crafted file fully controls the OOB length per tile and works with perfectly legal per-row run codes (no overlong runs needed).
Verified at commit 5cd4d0d26a82a9549f297a237aea9cf665bddff8 (main; latest release v4.1.0, the supported major).
Details
Root cause: a size mismatch between tile buffer allocation and decompressor width, because the factory drops the tile parameters.
- Allocation: TiffDecoderCore.cs#L792-L794 —
bytesPerTileRow = RoundUpToMultipleOfEight(tileWidth*bitsPerPixel); tile buffer =bytesPerTileRow*tileLengthbytes (32 bytes in the PoC) - Mismatch: TiffDecoderCore.cs#L797 —
CreateDecompressor<TPixel>(frame.Width, ..., isTiled: true, tileWidth, tileLength)passes the full frame width - Factory drops tile params: TiffDecompressorsFactory.cs#L56-L64 — T4/T6/MH decompressors receive only
width(= frame.Width);isTiled/tileWidth/tileHeightignored - OOB write sink: T4TiffCompression.cs#L69-L119,
T6TiffCompression.cs#L76-L108— per-row advance ofthis.widthbits viaBitWriterUtils.WriteBitswith no buffer-length check (BitWriterUtils.cs#L51); noteTiffDecoderCore.cs:829-831later reads the buffer inbytesPerTileRowstrides, confirming the protocol expects tile-width rows
Attack surface: Image.Load(stream) on an attacker-supplied tiled TIFF (TiffDecoderCore.DecodeImageWithTiles → DecodeTilesChunky). Default configuration; only requirement is a standard tiled TIFF header (TileWidth=16, TileLength=16) + Compression=3 (T4; T6 also constructible).
Suggested remediation:
- Short-term: when
isTiled, construct the T4/T6/MH decompressor withtileWidth(not frame width), or clip row writes to the caller-provided buffer length. - Root fix: bound the write side of
BitWriterUtils(pass remaining bits), and validate every fax row advance against buffer capacity on both tiled and strip paths. - Regression tests: Compression=2/3/4 × tiled with TileWidth < ImageWidth, including a T6 black-pixel row (forces real
WriteBit).
PoC
Full PoC posted as the first comment below: Program.cs (driver), poc-tiled-t4.tif (crafted file, ~9.8 KB, base64 inline), README.
-
Build a small console project referencing
src/ImageSharp/ImageSharp.csprojand run it against the crafted file (or callImage.Loadon it from any host). -
Observed with ImageWidth=4,000,000, TileWidth=16, TileLength=16, T4 with 400 makeup codes + EOL per row:
tile payload 9642 bytes; rows write ~2,048,000 bytes into a 32-byte buffer Fatal error. System.AccessViolationException: Attempted to read or write protected memory. at SixLabors.ImageSharp.Formats.Tiff.Compression.BitWriterUtils.WriteBits(Span`1<Byte>, IntPtr, IntPtr, Byte) at ...T4TiffCompression.WritePixelRun(...) at ...T4TiffCompression.Decompress(...) Aborted (core dumped); exit=134 -
Controls: the same file with Compression=None decodes normally (container is fine); a T6 all-white-rows variant advances >512 MB of bit offset without a real write (silent corruption window) before tripping on a directory-level TileOffsets count check.
Impact
- What it is: out-of-bounds write (CWE-787). For any service decoding untrusted tiled TIFFs: remote, default-configuration, deterministic process crash (DoS), plus a heap OOB write whose per-tile length and row width are attacker-tunable — a potential code-execution surface. This is a vulnerability in the library itself, in scope of your SECURITY.md.
- Who is impacted: applications decoding untrusted TIFF with SixLabors.ImageSharp at the current major (verified on main past v4.1.0); tiled + fax-compressed files are the trigger, which ordinary TIFF writers can produce.
Reported by Kimi Security Team ([email protected]).
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| .NETNuGet | ImageSharp | ≥ 3.0.0&&< 4.1.1 | 4.1.1dotnet add package ImageSharp --version 4.1.1 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for ImageSharp, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update ImageSharp to 4.1.1 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-106118 is resolved across your whole dependency graph.
Workarounds
Stop feeding it untrusted input: reject or quarantine files and payloads from unverified sources until you can upgrade, restrict accepted formats to the ones you actually need, and run the parsing or decoding step in a least-privileged sandbox or short-lived worker so a crash or corrupted read cannot reach the rest of the process.
Frequently Asked Questions
Is CVE-2026-106118 in your dependencies?
Find it across NuGet, including transitive dependencies.