---
id: "CVE-2026-106118"
kind: "vulnerability"
aliases: ["CVE-2026-106118", "GHSA-v76p-62qx-wwq2"]
title: "ImageSharp: Tiled fax TIFF: tile buffer sized by TileWidth but fax decompressor writes scanlines of ImageWidth \u2014 heap OOB write"
severity: "high"
cvss: 7.5
epss: 0.00595
exploited: false
status: "open"
category: "package"
products: [{"name": "ImageSharp", "fixed": ["3.2.0"], "affected": ">= 3.0.0, < 3.2.0", "ecosystem": "nuget"}, {"name": "ImageSharp", "fixed": ["4.1.1"], "affected": ">= 4.0.0, < 4.1.1", "ecosystem": "nuget"}, {"name": "SixLabors.ImageSharp", "fixed": ["3.2.0"], "affected": ">= 3.0.0, < 3.2.0", "ecosystem": "nuget"}, {"name": "SixLabors.ImageSharp", "fixed": ["4.1.1"], "affected": ">= 4.0.0, < 4.1.1", "ecosystem": "nuget"}]
ecosystems: ["nuget"]
tags: ["cwe-787", "dotnet", "image-processing", "nuget", "package", "self-hosted"]
not_affected_if: ["fixed-version", "no-untrusted-tiff", "tiff-not-decoded"]
published_at: "2026-10-06T19:17:42+00:00"
first_seen_at: "2026-10-26T14:16:25+00:00"
updated_at: "2026-10-26T16:04:20+00:00"
sources: [{"source": "ghsa", "url": "https://github.com/advisories/GHSA-v76p-62qx-wwq2", "first_seen_at": "2026-10-26T14:16:25+00:00"}, {"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-106118", "first_seen_at": "2026-10-26T14:30:37+00:00"}]
---

# ImageSharp: Tiled fax TIFF: tile buffer sized by TileWidth but fax decompressor writes scanlines of ImageWidth — heap OOB write

ImageSharp allocates tile buffers sized by TileWidth but decodes tiled T4/T6 fax TIFFs using the full image width, so each row writes past the buffer. A crafted TIFF passed to Image.Load causes a deterministic process crash and an out-of-bounds heap write that may be exploitable for code execution.

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- nuget:ImageSharp affected >= 3.0.0, < 3.2.0 fixed 3.2.0
- nuget:ImageSharp affected >= 4.0.0, < 4.1.1 fixed 4.1.1
- nuget:SixLabors.ImageSharp affected >= 3.0.0, < 3.2.0 fixed 3.2.0
- nuget:SixLabors.ImageSharp affected >= 4.0.0, < 4.1.1 fixed 4.1.1

## How to check

- Run `dotnet list package` in the project and look for `SixLabors.ImageSharp` below `3.2.0` or at `4.0.0` to `4.1.0`.
- Check whether the app decodes untrusted TIFF files with `Image.Load` and whether those files can be tiled with Compression=3 or 4.

## Fix

- Upgrade `SixLabors.ImageSharp` to `3.2.0` on the 3.x line.
- Upgrade `SixLabors.ImageSharp` to `4.1.1` on the 4.x line.
- Until upgraded, reject or do not decode untrusted tiled fax-compressed TIFF input.

## Timeline

- 2026-10-26T14:16:25+00:00 ghsa https://github.com/advisories/GHSA-v76p-62qx-wwq2
- 2026-10-26T14:30:37+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-106118

## From the sources

## 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](https://github.com/SixLabors/ImageSharp/blob/5cd4d0d26a82a9549f297a237aea9cf665bddff8/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs#L792-L794) — `bytesPerTileRow = RoundUpToMultipleOfEight(tileWidth*bitsPerPixel)`; tile buffer = `bytesPerTileRow*tileLength` bytes (32 bytes in the PoC)
- Mismatch: [TiffDecoderCore.cs#L797](https://github.com/SixLabors/ImageSharp/blob/5cd4d0d26a82a9549f297a237aea9cf665bddff8/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs#L797) — `CreateDecompressor<TPixel>(frame.Width, ..., isTiled: true, tileWidth, tileLength)` passes the full frame width
- Factory drops tile params: [TiffDecompressorsFactory.cs#L56-L64](https://github.com/SixLabors/ImageSharp/blob/5cd4d0d26a82a9549f297a237aea9cf665bddff8/src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs#L56-L64) — T4/T6/MH decompressors receive only `width` (= frame.Width); `isTiled/tileWidth/tileHeight` ignored
- OOB write sink: [T4TiffCompression.cs#L69-L119](https://github.com/SixLabors/ImageSharp/blob/5cd4d0d26a82a9549f297a237aea9cf665bddff8/src/ImageSharp/Formats/Tiff/Compression/Decompressors/T4TiffCompression.cs#L69-L119), `T6TiffCompression.cs#L76-L108` — per-row advance of `this.width` bits via `BitWriterUtils.WriteBits` with no buffer-length check ([BitWriterUtils.cs#L51](https://github.com/SixLabors/ImageSharp/blob/5cd4d0d26a82a9549f297a237aea9cf665bddff8/src/ImageSharp/Formats/Tiff/Compression/BitWriterUtils.cs#L51)); note `TiffDecoderCore.cs:829-831` later reads the buffer in `bytesPerTileRow` strides, 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:**
1. Short-term: when `isTiled`, construct the T4/T6/MH decompressor with `tileWidth` (not frame width), or clip row writes to the caller-provided buffer length.
2. 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.
3. 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.

1. Build a small console project referencing `src/ImageSharp/ImageSharp.csproj` and run it against the crafted file (or call `Image.Load` on it from any host).
2. 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
   ```

3. 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** (bug-report@moonshot.ai).

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
