{"id":"CVE-2026-106118","kind":"vulnerability","aliases":["CVE-2026-106118","GHSA-v76p-62qx-wwq2"],"related":[],"title":"ImageSharp: Tiled fax TIFF: tile buffer sized by TileWidth but fax decompressor writes scanlines of ImageWidth — heap OOB write","description":"## Summary\n\nWhen 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).\n\nVerified at commit `5cd4d0d26a82a9549f297a237aea9cf665bddff8` (main; latest release v4.1.0, the supported major).\n\n## Details\n\nRoot cause: a size mismatch between tile buffer allocation and decompressor width, because the factory drops the tile parameters.\n\n- 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)\n- 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\n- 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\n- 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\n\nAttack 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).\n\n**Suggested remediation:**\n1. 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.\n2. 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.\n3. Regression tests: Compression=2/3/4 × tiled with TileWidth < ImageWidth, including a T6 black-pixel row (forces real `WriteBit`).\n\n## PoC\n\nFull PoC posted as the first comment below: `Program.cs` (driver), `poc-tiled-t4.tif` (crafted file, ~9.8 KB, base64 inline), README.\n\n1. 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).\n2. Observed with ImageWidth=4,000,000, TileWidth=16, TileLength=16, T4 with 400 makeup codes + EOL per row:\n\n   ```\n   tile payload 9642 bytes; rows write ~2,048,000 bytes into a 32-byte buffer\n   Fatal error. System.AccessViolationException: Attempted to read or write protected memory.\n      at SixLabors.ImageSharp.Formats.Tiff.Compression.BitWriterUtils.WriteBits(Span`1<Byte>, IntPtr, IntPtr, Byte)\n      at ...T4TiffCompression.WritePixelRun(...)\n      at ...T4TiffCompression.Decompress(...)\n   Aborted (core dumped); exit=134\n   ```\n\n3. 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.\n\n## Impact\n\n- **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.\n- **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.\n\n---\n\n---\n\nReported by **Kimi Security Team** (bug-report@moonshot.ai).","summary":"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.","severity":"high","cvss":7.5,"epss":0.00595,"exploited":false,"exploited_at":null,"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"],"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`.\n- 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.\n- Upgrade `SixLabors.ImageSharp` to `4.1.1` on the 4.x line.\n- Until upgraded, reject or do not decode untrusted tiled fax-compressed TIFF input.","status":"open","published_at":"2026-10-06T19:17:42+00:00","first_seen_at":"2026-10-26T14:16:25+00:00","triaged_at":"2026-10-26T14:17:32+00:00","updated_at":"2026-10-26T16:04:20+00:00","category":"package","confidence":0.8,"triage":{"at":"2026-10-26T14:17:32Z","model":"claude-haiku-5-5","output":{"fix":"- Upgrade `SixLabors.ImageSharp` to `3.2.0` on the 3.x line.\n- Upgrade `SixLabors.ImageSharp` to `4.1.1` on the 4.x line.\n- Until upgraded, reject or do not decode untrusted tiled fax-compressed TIFF input.","reach":"internet","title":"ImageSharp: crafted tiled fax TIFF writes past tile buffer, crashing decoder","impact":"high","summary":"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.","category":"package","nicknames":[],"who_cares":["dotnet","nuget","image-processing","self-hosted"],"confidence":0.8,"needs_auth":"no","worst_case":"Process crashes; heap write may allow code execution.","analyst_note":"Check whether the sources confirm a published fixed release note and whether any exploit beyond crash has been demonstrated; see https://github.com/advisories/GHSA-v76p-62qx-wwq2.","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`.\n- Check whether the app decodes untrusted TIFF files with `Image.Load` and whether those files can be tiled with Compression=3 or 4.","needs_analyst":true,"not_affected_if":["no-untrusted-tiff","tiff-not-decoded","fixed-version"],"who_is_affected":"Applications that call ImageSharp to decode untrusted TIFF files are exposed, because a single crafted tiled T4 or T6 file is enough to trigger the write. Exposure needs a tiled TIFF with fax compression reaching the decoder; applications that only process images they create, or that never load TIFF, can skip it.","user_interaction":"no","needs_special_setup":"no","severity_if_unknown":"high"},"cost_usd":0.000953,"input_tokens":5789,"output_tokens":748,"severity_before":"high"},"analyst_status":null,"analyst_note":null,"search":"'-106118':22A,30A '-2026':21A,29A '-787':36B '-831':389C '/sixlabors/imagesharp/blob/5cd4d0d26a82a9549f297a237aea9cf665bddff8/src/imagesharp/formats/tiff/compression/bitwriterutils.cs#l51));':386C '/sixlabors/imagesharp/blob/5cd4d0d26a82a9549f297a237aea9cf665bddff8/src/imagesharp/formats/tiff/compression/decompressors/t4tiffcompression.cs#l69-l119),':362C '/sixlabors/imagesharp/blob/5cd4d0d26a82a9549f297a237aea9cf665bddff8/src/imagesharp/formats/tiff/compression/tiffdecompressorsfactory.cs#l56-l64)':344C '/sixlabors/imagesharp/blob/5cd4d0d26a82a9549f297a237aea9cf665bddff8/src/imagesharp/formats/tiff/tiffdecodercore.cs#l792-l794)':302C '/sixlabors/imagesharp/blob/5cd4d0d26a82a9549f297a237aea9cf665bddff8/src/imagesharp/formats/tiff/tiffdecodercore.cs#l797)':322C '000':193C,194C '1':440C,531C '16':196C,198C,429C,431C '2':201C,466C '2/3/4':497C '3':433C,493C '32':205C,312C '4':192C '512':224C '5cd4d0d26a82a9549f297a237aea9cf665bddff8':267C '62qx':26A '9.8':526C 'advanc':145C,219C,370C,483C 'alarm':230C 'alarm-fre':229C 'all-whit':215C 'alloc':47B,108C,284C,295C 'also':436C 'attack':405C,412C 'attacker-suppli':411C 'base64':528C 'bit':154C,157C,221C,373C,477C 'bitsperpixel':306C 'bitwriterutil':474C 'bitwriterutils.cs':382C 'bitwriterutils.writebits':375C 'black':506C 'black-pixel':505C 'bound':87B,162C,177C,469C 'bpp/8':116C 'buffer':6A,49B,70B,111C,167C,189C,207C,283C,308C,379C,393C,464C,485C 'buffer-length':378C 'build':532C 'byte':118C,180C,206C,311C,313C 'bytespertilerow':303C,309C,395C 'caller':462C 'caller-provid':461C 'capac':486C 'caus':77B,277C 'ceil':114C 'check':163C,381C 'clip':456C 'code':95B,259C 'comment':519C 'commit':266C 'compress':105C,432C,496C 'configur':419C 'confirm':397C 'consol':535C 'construct':120C,437C,446C 'control':244C 'corrupt':234C 'craft':72B,241C,524C,544C 'crash':81B 'createdecompressor':323C 'cve':20A,28A 'cwe':35B 'decod':54B,99C 'decodetileschunki':107C,417C 'decompressor':12A,123C,134C,286C,346C,449C 'default':418C 'defect':239C 'detail':275C 'determinist':79B,212C 'dotnet':37B 'driver':522C 'drop':291C,335C 'entir':131C 'everi':480C 'execut':96B 'expect':400C 'exploit':93B 'factori':290C,334C 'fax':3A,11A,57B,104C,122C,481C 'file':242C,525C,545C 'first':170C,518C 'fix':468C 'forc':509C 'frame':332C,453C 'frame.width':125C,156C,324C,350C 'free':231C 'full':61B,137C,331C,513C 'fulli':243C 'ghsa':24A 'ghsa-v76p-62qx-wwq2':23A 'github.com':301C,321C,343C,361C,385C 'github.com/sixlabors/imagesharp/blob/5cd4d0d26a82a9549f297a237aea9cf665bddff8/src/imagesharp/formats/tiff/compression/bitwriterutils.cs#l51));':384C 'github.com/sixlabors/imagesharp/blob/5cd4d0d26a82a9549f297a237aea9cf665bddff8/src/imagesharp/formats/tiff/compression/decompressors/t4tiffcompression.cs#l69-l119),':360C 'github.com/sixlabors/imagesharp/blob/5cd4d0d26a82a9549f297a237aea9cf665bddff8/src/imagesharp/formats/tiff/compression/tiffdecompressorsfactory.cs#l56-l64)':342C 'github.com/sixlabors/imagesharp/blob/5cd4d0d26a82a9549f297a237aea9cf665bddff8/src/imagesharp/formats/tiff/tiffdecodercore.cs#l792-l794)':300C 'github.com/sixlabors/imagesharp/blob/5cd4d0d26a82a9549f297a237aea9cf665bddff8/src/imagesharp/formats/tiff/tiffdecodercore.cs#l797)':320C 'header':427C 'heap':17A,88B,233C 'heap-corrupt':232C 'host':45B 'ignor':127C,352C 'imag':39B,62B,138C 'image-process':38B 'image.load':76B,407C 'imagesharp':1A,31A,32A,46B 'imagewidth':16A,191C,501C 'imagewidth/8':179C 'includ':502C 'inlin':529C 'istil':325C,445C 'istiled/tilewidth/tileheight':129C,351C 'kb':527C 'kill':209C 'l108':366C 'l119':359C 'l51':383C 'l56':340C 'l56-l64':339C 'l64':341C 'l69':358C 'l69-l119':357C 'l76':365C 'l76-l108':364C 'l792':298C 'l792-l794':297C 'l794':299C 'l797':319C 'later':390C 'latest':269C 'legal':254C 'length':143C,247C,380C,465C 'linear':174C 'main':268C 'major':274C 'may':91B 'mb':202C,225C 'mismatch':280C,317C 'modifi':152C 'need':263C 'note':387C 'nuget':41B 'offset':222C 'oob':18A,246C,353C 'op':155C 'out-of-bound':84B 'overlong':261C 'packag':42B 'param':337C 'paramet':130C,294C 'pass':74B,329C,475C 'past':68B,203C 'path':492C 'per':158C,181C,248C,256C,368C 'per-row':255C,367C 'perfect':253C 'pixel':507C 'poc':316C,512C,514C 'poc-tiled-t4.tif':523C 'post':515C 'process':40B,80B,211C 'program.cs':521C 'project':536C 'protocol':399C 'provid':463C 'read':151C,391C 'read-modify-writ':150C 'readm':530C 'real':510C 'realli':147C 'receiv':347C 'referenc':537C 'regress':494C 'releas':270C 'remain':476C 'remedi':439C 'requir':421C 'root':276C,467C 'rounduptomultipleofeight':304C 'row':66B,159C,182C,184C,257C,369C,404C,457C,482C,508C 'run':258C,262C,540C 'scanlin':14A,142C 'self':44B 'self-host':43B 'short':442C 'short-term':441C 'show':227C 'side':472C 'silent':226C 'sink':355C 'sixlabors.imagesharp':33A,34A 'size':7A,50B,188C,279C 'small':534C 'src/imagesharp/imagesharp.csproj':538C 'standard':424C 'stream':408C 'stride':396C 'strip':491C 'suggest':438C 'summari':97C 'suppli':413C 'support':273C 'surfac':406C 't4':434C 't4/t6':56B 't4/t6/mh':106C,133C,345C,448C 't4tiffcompression.cs':356C 't6':214C,435C,504C 't6tiffcompression.cs':363C 'term':443C 'test':495C 'therefor':172C 'this.width':372C 'tiff':4A,58B,73B,102C,415C,426C 'tiffdecodercore.cs':296C,318C 'tiffdecodercore.cs:829':388C 'tiffdecodercore.decodeimagewithtiles':416C 'tiffdecompressorsfactori':126C 'tiffdecompressorsfactory.cs':338C 'tile':2A,5A,48B,55B,101C,110C,166C,171C,249C,282C,293C,307C,336C,402C,414C,425C,489C,498C 'tile-width':401C 'tilelength':117C,183C,197C,310C,328C,430C 'tilewidth':9A,52B,113C,115C,187C,195C,305C,327C,428C,451C,500C 'treat':135C 'true':326C 'use':59B 'v4.1.0':271C 'v76p':25A 'valid':479C 'variant':218C 'verifi':264C 'via':149C,374C 'white':217C 'width':63B,139C,287C,333C,349C,403C,454C 'window':235C 'work':251C 'write':13A,19A,67B,89B,148C,153C,173C,200C,354C,458C,471C 'writebit':511C 'wwq2':27A","nicknames":[],"mitigations":[],"who_affected":"Applications that call ImageSharp to decode untrusted TIFF files are exposed, because a single crafted tiled T4 or T6 file is enough to trigger the write. Exposure needs a tiled TIFF with fax compression reaching the decoder; applications that only process images they create, or that never load TIFF, can skip it.","tier":"B","verified":{},"analyst_revisit_at":null,"first_public_at":"2026-10-06T19:17:42+00:00","kev":null,"cvss_vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","cvss_by":"GitHub","poc_count":0,"sources":[{"source":"ghsa","external_id":"GHSA-v76p-62qx-wwq2","url":"https://github.com/advisories/GHSA-v76p-62qx-wwq2","severity":"high","published_at":"2026-10-07T16:18:57+00:00","modified_at":"2026-10-26T16:04:12+00:00","first_seen_at":"2026-10-26T14:16:25+00:00","fetched_at":"2026-10-26T16:04:20+00:00","note":null},{"source":"nvd","external_id":"CVE-2026-106118","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-106118","severity":null,"published_at":"2026-10-06T19:17:42+00:00","modified_at":"2026-10-06T20:17:17+00:00","first_seen_at":"2026-10-26T14:30:37+00:00","fetched_at":"2026-10-26T14:30:37+00:00","note":null}],"documents":[],"notice":"Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai"}