Vulnerable packages at v26.16.0: System.Security.Cryptography.Pkcs 9.0.4 (High, transitive) and ImageSharp 3.1.12 (Moderate) #929

Open
opened 2026-10-22 08:15:52 +02:00 by timothy · 5 comments
Owner

dotnet list ErsatzTV.sln package --vulnerable --include-transitive, run 2026-10-22 as part of the v26.16.0 release cut, reports two advisories. Both were published after v26.15.0 and are present in that prod build too, so v26.16.0 ships them unchanged rather than introducing them.

Advisory Package Severity Path into the build Fixed in
GHSA-846f-f764-76mx (CVE-2026-84008, .NET DoS) System.Security.Cryptography.Pkcs 9.0.4 (transitive) High EFCore.BulkExtensions 9.0.2 → .Oracle/.SqlServer → Oracle.ManagedDataAccess.Core 23.9.0 (dotnet nuget why) 9.0.21
GHSA-gwg2-r3hj-4w44 (ICC CLUT parsing allocates from unvalidated dimensions) SixLabors.ImageSharp 3.1.12 (direct) Moderate logo/artwork processing, including external-URL logos downloaded at save time (#525) 4.1.2 only (major); Renovate PR #923

Reachability (unmeasured)

  • Pkcs: reached only via the Oracle/SQL Server bulk-extension providers, which ErsatzTV never configures at runtime (SQLite/MySQL only). Likely unreachable. Even so, pin it: an unreachable High still fails every vulnerability scan and hides real findings.
  • ImageSharp: reachable whenever ErsatzTV decodes an image it didn't produce: Jellyfin artwork, and external logo URLs. Bounded by the remote-fetch size/decode caps from #511, but those cap bytes, not ICC table dimensions.

Done-when

  • System.Security.Cryptography.Pkcs resolves to >= 9.0.21 in every project. Via a central transitive pin (CentralPackageTransitivePinningEnabled + <PackageVersion>), or by dropping the unused Oracle/SqlServer BulkExtensions providers if the core package allows it. The vulnerable scan no longer lists it.
  • ImageSharp moved to >= 4.1.2 (review #923 for v4 API/behaviour changes in logo generation, watermark and artwork paths, with existing image tests green), OR a dated decision record explaining why 3.x is kept and what bounds the ICC path
  • dotnet list package --vulnerable --include-transitive clean, or every remaining entry justified in the PR
  • Adversarial review passed

refs #924 (found during the v26.16.0 cut)

`dotnet list ErsatzTV.sln package --vulnerable --include-transitive`, run 2026-10-22 as part of the v26.16.0 release cut, reports two advisories. Both were published after v26.15.0 and are present in that prod build too, so v26.16.0 ships them unchanged rather than introducing them. | Advisory | Package | Severity | Path into the build | Fixed in | |---|---|---|---|---| | [GHSA-846f-f764-76mx](https://github.com/advisories/GHSA-846f-f764-76mx) (CVE-2026-84008, .NET DoS) | `System.Security.Cryptography.Pkcs` 9.0.4 (transitive) | High | `EFCore.BulkExtensions` 9.0.2 → `.Oracle`/`.SqlServer` → `Oracle.ManagedDataAccess.Core` 23.9.0 (`dotnet nuget why`) | 9.0.21 | | [GHSA-gwg2-r3hj-4w44](https://github.com/advisories/GHSA-gwg2-r3hj-4w44) (ICC CLUT parsing allocates from unvalidated dimensions) | `SixLabors.ImageSharp` 3.1.12 (direct) | Moderate | logo/artwork processing, including external-URL logos downloaded at save time (#525) | 4.1.2 only (major); Renovate PR #923 | ## Reachability (unmeasured) - **Pkcs:** reached only via the Oracle/SQL Server bulk-extension providers, which ErsatzTV never configures at runtime (SQLite/MySQL only). Likely unreachable. Even so, pin it: an unreachable High still fails every vulnerability scan and hides real findings. - **ImageSharp:** reachable whenever ErsatzTV decodes an image it didn't produce: Jellyfin artwork, and external logo URLs. Bounded by the remote-fetch size/decode caps from #511, but those cap bytes, not ICC table dimensions. ## Done-when - [x] `System.Security.Cryptography.Pkcs` resolves to >= 9.0.21 in every project. Via a central transitive pin (`CentralPackageTransitivePinningEnabled` + `<PackageVersion>`), or by dropping the unused Oracle/SqlServer BulkExtensions providers if the core package allows it. The vulnerable scan no longer lists it. - [x] ImageSharp moved to >= 4.1.2 (review #923 for v4 API/behaviour changes in logo generation, watermark and artwork paths, with existing image tests green), OR a dated decision record explaining why 3.x is kept and what bounds the ICC path - [x] `dotnet list package --vulnerable --include-transitive` clean, or every remaining entry justified in the PR - [x] Adversarial review passed refs #924 (found during the v26.16.0 cut)
timothy added the priority: high label 2026-10-27 21:29:00 +01:00
timothy added the in-progress label 2026-10-27 21:33:05 +01:00
Author
Owner

Claimed by an orchestrated slot: branch 929-vuln-pkcs-imagesharp-v4, worktree /Users/timothy/orca/workspaces/ersatztv/wt-929. Plan: central transitive pin for System.Security.Cryptography.Pkcs >= 9.0.21, ImageSharp -> 4.x (supersedes Renovate PR #923), pixel/md5 comparison of logo + watermark output 3.x vs 4.x.

Claimed by an orchestrated slot: branch `929-vuln-pkcs-imagesharp-v4`, worktree `/Users/timothy/orca/workspaces/ersatztv/wt-929`. Plan: central transitive pin for System.Security.Cryptography.Pkcs >= 9.0.21, ImageSharp -> 4.x (supersedes Renovate PR #923), pixel/md5 comparison of logo + watermark output 3.x vs 4.x.
Author
Owner

Implementation status (slot worktree /Users/timothy/orca/workspaces/ersatztv/wt-929, branch 929-vuln-pkcs-imagesharp-v4, not pushed yet; review pending).

Pkcs: done. System.Security.Cryptography.Pkcs 9.0.21 is now a direct reference in ErsatzTV.Infrastructure.csproj, following the existing Microsoft.OpenApi / SQLitePCLRaw pattern. All 11 projects resolve 9.0.21, and the scan no longer lists it. The central transitive pin was tried and rejected: CentralPackageTransitivePinningEnabled fails restore with NU1109 in every project, because Microsoft.Extensions.DependencyModel is exact-pinned at [8.0.2], below the >= 9.0.x that EF Core requires.

ImageSharp: the issue's premise does not hold. 4.1.2 is not a drop-in bump.

  • Every patched release (3.2.0 fixes them all on the 3.x line; 4.1.2/4.1.3 on 4.x) ships a SixLabors_ValidateLicense MSBuild target. It fails a Release build when no Six Labors license key is set (measured: dotnet build -c Release errors No Six Labors license found on 3.2.0 and 4.1.3; Debug only warns). CI and the Docker image build Release, so #923 as it stands would turn every PR red. 3.1.12 has no such target. The license text itself is byte-identical across these versions.
  • The scan on 3.1.12 now lists six advisories, not one: v76p (High, TIFF decoder heap OOB write), wmxv (TIFF BigTIFF loop), jjfr and j9gm (TIFF encoders), j3p4 (HistogramEqualization) and gwg2 (ICC accessor).
  • What the branch does: ImageSharp stays on 3.1.12. Every ImageSharp decode (Identify + Load, remote + local) goes through a configuration that cannot detect TIFF. That covers the two decoder advisories. ErsatzTV never calls the other four code paths. The record is security.imagesharp-3x-tiff-decoder-disabled.
  • Consequence: the weekly dependency-scan.yml stays red on ImageSharp. dotnet list --vulnerable ignores NuGetAuditSuppress (measured), so suppressing the advisories cannot turn it green.
  • Owner decision needed for the clean fix: apply for a Six Labors Community license key (free below USD 1M revenue, application-based), provision it as a CI secret and Docker build arg (SixLaborsLicenseKey), then bump and re-measure the #511 decoder behaviours.

Live E2E (local, port 8500, origin/main e919b925f vs branch): a PNG watermark rendered through /ffmpeg/stream/929 gives an identical frame md5 (fb1a68cb…, 64x64 red block at 96,54) on both builds. A channel logo URL pointing at a TIFF is 201 on main and 422 on the branch, and the 422's decoder list has no TIFF. A PNG logo URL is 201 on both.

Implementation status (slot worktree `/Users/timothy/orca/workspaces/ersatztv/wt-929`, branch `929-vuln-pkcs-imagesharp-v4`, not pushed yet; review pending). **Pkcs: done.** `System.Security.Cryptography.Pkcs` 9.0.21 is now a direct reference in `ErsatzTV.Infrastructure.csproj`, following the existing Microsoft.OpenApi / SQLitePCLRaw pattern. All 11 projects resolve 9.0.21, and the scan no longer lists it. The central transitive pin was tried and rejected: `CentralPackageTransitivePinningEnabled` fails restore with NU1109 in every project, because `Microsoft.Extensions.DependencyModel` is exact-pinned at `[8.0.2]`, below the `>= 9.0.x` that EF Core requires. **ImageSharp: the issue's premise does not hold. 4.1.2 is not a drop-in bump.** - Every patched release (3.2.0 fixes them all on the 3.x line; 4.1.2/4.1.3 on 4.x) ships a `SixLabors_ValidateLicense` MSBuild target. It fails a **Release** build when no Six Labors license key is set (measured: `dotnet build -c Release` errors `No Six Labors license found` on 3.2.0 and 4.1.3; Debug only warns). CI and the Docker image build Release, so #923 as it stands would turn every PR red. 3.1.12 has no such target. The license text itself is byte-identical across these versions. - The scan on 3.1.12 now lists **six** advisories, not one: v76p (High, TIFF decoder heap OOB write), wmxv (TIFF BigTIFF loop), jjfr and j9gm (TIFF encoders), j3p4 (HistogramEqualization) and gwg2 (ICC accessor). - What the branch does: ImageSharp stays on 3.1.12. Every ImageSharp decode (Identify + Load, remote + local) goes through a configuration that cannot detect TIFF. That covers the two decoder advisories. ErsatzTV never calls the other four code paths. The record is `security.imagesharp-3x-tiff-decoder-disabled`. - Consequence: the weekly `dependency-scan.yml` stays red on ImageSharp. `dotnet list --vulnerable` ignores `NuGetAuditSuppress` (measured), so suppressing the advisories cannot turn it green. - **Owner decision needed for the clean fix:** apply for a Six Labors Community license key (free below USD 1M revenue, application-based), provision it as a CI secret and Docker build arg (`SixLaborsLicenseKey`), then bump and re-measure the #511 decoder behaviours. **Live E2E (local, port 8500, origin/main `e919b925f` vs branch):** a PNG watermark rendered through `/ffmpeg/stream/929` gives an identical frame md5 (`fb1a68cb…`, 64x64 red block at 96,54) on both builds. A channel logo URL pointing at a TIFF is **201 on main and 422 on the branch**, and the 422's decoder list has no TIFF. A PNG logo URL is 201 on both.
Author
Owner

Live E2E re-run on the branch head after review (local, port 8500, 2026-10-27, ETV_UI_PORT=8500 scripts/e2e-local.sh <fresh CONFIG_DIR>, same assets for both builds, asset server on 127.0.0.1:8501).

Base vs branch. The branch keeps ImageSharp 3.1.12, so there is no 4.x output to compare. What changed for rendering is the decode call sites. The base build is the branch with RemoteImageValidator.cs and ImageElementBase.cs checked out from origin/main e919b925f, which restores the default-configuration decodes. That build answers a TIFF logo URL with 201, so it really is the old decode path. The branch answers 422, and the decoder list in the response has no TIFF.

Channel logo render. Each channel's logo was saved from a URL, which goes through RemoteLogoCacher -> RemoteImageValidator. It was then drawn on stream by a ChannelLogo watermark through the graphics engine (ImageElementBase). The first video frame of /ffmpeg/stream/<n>?mode=ts-legacy was decoded to rgb24 and hashed:

Logo (96x64) Build Full-frame md5 Logo-region md5 (96,54 96x64) Cached logo md5
PNG, RGBA half alpha base 7b2c924130b8616ff33d3a73da0451b7 a8d915f67898fe4145a2c810fa972cfb 92dbe332… (= source)
PNG, RGBA half alpha branch 7b2c924130b8616ff33d3a73da0451b7 a8d915f67898fe4145a2c810fa972cfb 92dbe332… (= source)
JPEG base 277e232fb023f90e6ef73b164908ed1d 453416fb9227b99c0a763f83a4ef211e ac20d212… (= source)
JPEG branch 277e232fb023f90e6ef73b164908ed1d 453416fb9227b99c0a763f83a4ef211e ac20d212… (= source)

The logo is visibly composited at (96,54) on both builds: a pixel inside it reads (36,6,60) for PNG and (25,4,59) for JPEG, against a (26,65,129) background. /iptv/logos/gen?text=E2E929 is 5f215b44… on both.

Watermark render. A custom PNG watermark (64x64 red) gives frame md5 fb1a68cb29a6afab3325c641ec738f79 on both builds, with the red bbox at (96,54)-(159,117) and 4096 red pixels.

Live E2E re-run on the branch head after review (local, port 8500, 2026-10-27, `ETV_UI_PORT=8500 scripts/e2e-local.sh <fresh CONFIG_DIR>`, same assets for both builds, asset server on 127.0.0.1:8501). **Base vs branch.** The branch keeps ImageSharp 3.1.12, so there is no 4.x output to compare. What changed for rendering is the decode call sites. The base build is the branch with `RemoteImageValidator.cs` and `ImageElementBase.cs` checked out from origin/main `e919b925f`, which restores the default-configuration decodes. That build answers a TIFF logo URL with **201**, so it really is the old decode path. The branch answers **422**, and the decoder list in the response has no TIFF. **Channel logo render.** Each channel's logo was saved from a URL, which goes through `RemoteLogoCacher` -> `RemoteImageValidator`. It was then drawn on stream by a `ChannelLogo` watermark through the graphics engine (`ImageElementBase`). The first video frame of `/ffmpeg/stream/<n>?mode=ts-legacy` was decoded to rgb24 and hashed: | Logo (96x64) | Build | Full-frame md5 | Logo-region md5 (96,54 96x64) | Cached logo md5 | |---|---|---|---|---| | PNG, RGBA half alpha | base | `7b2c924130b8616ff33d3a73da0451b7` | `a8d915f67898fe4145a2c810fa972cfb` | `92dbe332…` (= source) | | PNG, RGBA half alpha | branch | `7b2c924130b8616ff33d3a73da0451b7` | `a8d915f67898fe4145a2c810fa972cfb` | `92dbe332…` (= source) | | JPEG | base | `277e232fb023f90e6ef73b164908ed1d` | `453416fb9227b99c0a763f83a4ef211e` | `ac20d212…` (= source) | | JPEG | branch | `277e232fb023f90e6ef73b164908ed1d` | `453416fb9227b99c0a763f83a4ef211e` | `ac20d212…` (= source) | The logo is visibly composited at (96,54) on both builds: a pixel inside it reads (36,6,60) for PNG and (25,4,59) for JPEG, against a (26,65,129) background. `/iptv/logos/gen?text=E2E929` is `5f215b44…` on both. **Watermark render.** A custom PNG watermark (64x64 red) gives frame md5 `fb1a68cb29a6afab3325c641ec738f79` on both builds, with the red bbox at (96,54)-(159,117) and 4096 red pixels.
Author
Owner

Done

What was done: Adversarial correctness/security review of bd24d21e23f363da3fc5ea5262b78671172d495a using git diff origin/main...HEAD. Blocking: none. Should-fix: none. Nit: none. VERDICT: merge.

Root cause: Existing vulnerable dependencies; Pkcs is overridden directly and ImageSharp remains under the explicitly accepted dated TIFF-disabled exception.

Files changed: None; inspection only. No commit or push.

Verification: All 17 solution project assets exist; Pkcs resolves to 9.0.21 in all 11 containing it and is absent from six. Recorded gate-r2 logs show Infrastructure.Tests 123 passed and Architecture.Tests 12 passed. vuln-r2.txt lists only the six ImageSharp advisories covered by the record. TIFF exclusion is behavior-tested and decode/configuration/forbidden API use is checked in compiled production IL. The gwg2 ICC runtime half is honestly labelled as ImageSharp 3.1.12 behavior; tests preserve the profile across validator/clone/resize/CloneAs, enforce an allocation ceiling, and prove the hostile fixture with an Entries-allocation positive control. The carrier-roundtrip limitation and watermark allocation-only limitation are explicit. No fresh dotnet run because this sandbox cannot run it; no PR exists, neither is a defect.

Deferred: Provision Six Labors licensing and upgrade ImageSharp per the existing record. This review does not close the implementation issue.

Follow-up issues: None added.

Docs updated: None; reviewed docs/decisions/records/security/imagesharp-3x-tiff-decoder-disabled.md, especially lines 44-94.

## Done **What was done**: Adversarial correctness/security review of `bd24d21e23f363da3fc5ea5262b78671172d495a` using `git diff origin/main...HEAD`. Blocking: none. Should-fix: none. Nit: none. VERDICT: merge. **Root cause**: Existing vulnerable dependencies; Pkcs is overridden directly and ImageSharp remains under the explicitly accepted dated TIFF-disabled exception. **Files changed**: None; inspection only. No commit or push. **Verification**: All 17 solution project assets exist; Pkcs resolves to 9.0.21 in all 11 containing it and is absent from six. Recorded gate-r2 logs show Infrastructure.Tests 123 passed and Architecture.Tests 12 passed. `vuln-r2.txt` lists only the six ImageSharp advisories covered by the record. TIFF exclusion is behavior-tested and decode/configuration/forbidden API use is checked in compiled production IL. The gwg2 ICC runtime half is honestly labelled as ImageSharp 3.1.12 behavior; tests preserve the profile across validator/clone/resize/CloneAs, enforce an allocation ceiling, and prove the hostile fixture with an Entries-allocation positive control. The carrier-roundtrip limitation and watermark allocation-only limitation are explicit. No fresh dotnet run because this sandbox cannot run it; no PR exists, neither is a defect. **Deferred**: Provision Six Labors licensing and upgrade ImageSharp per the existing record. This review does not close the implementation issue. **Follow-up issues**: None added. **Docs updated**: None; reviewed `docs/decisions/records/security/imagesharp-3x-tiff-decoder-disabled.md`, especially lines 44-94.
Author
Owner

Closing record

PR: http://192.168.1.95:3000/timothy/ersatztv/pulls/934 (head bd24d21e2, supersedes Renovate #923). Not closed by this slot; the orchestrator closes #923 and ticks Done-when after merge.

What was done: Pkcs pinned to 9.0.21 via a direct reference in ErsatzTV.Infrastructure; ImageSharp held at 3.1.12 with TIFF decoding removed from the one decode configuration (ImageSharpDecoding), under decision record security.imagesharp-3x-tiff-decoder-disabled; IL-scan architecture tests plus allocation-pinned ICC tests enforce the bounds; Renovate holds ImageSharp on 3.1.x.

Gate (head bd24d21e2): Release build 0 errors; all .NET test projects green (Infrastructure 136, ErsatzTV.Tests 2142, Core 720, Scanner 1504, FFmpeg 83, Mcp 61, Architecture 12); vitest 1371; pytest 1599. Output: /private/tmp/claude-501/-Users-timothy-ersatztv/f9ce6bc6-5b36-491a-8d72-89c1f70dd3e1/scratchpad/e2e929/gate-bd24d21e23f363da3fc5ea5262b78671172d495a.txt

Vulnerable scan: only SixLabors.ImageSharp 3.1.12 remains (6 advisories), each justified in the record table.

Done-when evidence

  • Pkcs >= 9.0.21 in every project: dotnet list ErsatzTV.sln package --vulnerable --include-transitive no longer lists Pkcs (gate file); direct reference in ErsatzTV.Infrastructure.csproj + Directory.Packages.props. Note the box's suggested mechanism (transitive pinning) was tried and fails NU1109; the direct reference achieves the outcome.
  • ImageSharp >= 4.1.2 OR dated decision record: record docs/decisions/records/security/imagesharp-3x-tiff-decoder-disabled.md (the OR branch); ImageSharpSurfaceTests and ImageSharpDecodingTests green in the gate file; live-E2E at comment 34502.
  • Vulnerable scan clean or each entry justified: gate file scan section plus the PR body table and the record table.
  • Adversarial review passed: 2-round review history in the PR body (round 2 clean); scripts/post-review-verdict.sh 934 still to be run by the orchestrator on the head.
## Closing record PR: http://192.168.1.95:3000/timothy/ersatztv/pulls/934 (head bd24d21e2, supersedes Renovate #923). Not closed by this slot; the orchestrator closes #923 and ticks Done-when after merge. **What was done**: Pkcs pinned to 9.0.21 via a direct reference in ErsatzTV.Infrastructure; ImageSharp held at 3.1.12 with TIFF decoding removed from the one decode configuration (`ImageSharpDecoding`), under decision record `security.imagesharp-3x-tiff-decoder-disabled`; IL-scan architecture tests plus allocation-pinned ICC tests enforce the bounds; Renovate holds ImageSharp on 3.1.x. **Gate** (head bd24d21e2): Release build 0 errors; all .NET test projects green (Infrastructure 136, ErsatzTV.Tests 2142, Core 720, Scanner 1504, FFmpeg 83, Mcp 61, Architecture 12); vitest 1371; pytest 1599. Output: /private/tmp/claude-501/-Users-timothy-ersatztv/f9ce6bc6-5b36-491a-8d72-89c1f70dd3e1/scratchpad/e2e929/gate-bd24d21e23f363da3fc5ea5262b78671172d495a.txt **Vulnerable scan**: only SixLabors.ImageSharp 3.1.12 remains (6 advisories), each justified in the record table. ### Done-when evidence - Pkcs >= 9.0.21 in every project: `dotnet list ErsatzTV.sln package --vulnerable --include-transitive` no longer lists Pkcs (gate file); direct reference in ErsatzTV.Infrastructure.csproj + Directory.Packages.props. Note the box's suggested mechanism (transitive pinning) was tried and fails NU1109; the direct reference achieves the outcome. - ImageSharp >= 4.1.2 OR dated decision record: record `docs/decisions/records/security/imagesharp-3x-tiff-decoder-disabled.md` (the OR branch); `ImageSharpSurfaceTests` and `ImageSharpDecodingTests` green in the gate file; live-E2E at comment 34502. - Vulnerable scan clean or each entry justified: gate file scan section plus the PR body table and the record table. - Adversarial review passed: 2-round review history in the PR body (round 2 clean); `scripts/post-review-verdict.sh 934` still to be run by the orchestrator on the head.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: timothy/ersatztv#929