Skip to content

fix(azure): drop unused SignalR extension to clear MessagePack CVE-2026-48109#329

Draft
mrostan wants to merge 1 commit into
mainfrom
mrostan/azure-drop-signalr-cve-2026-48109
Draft

fix(azure): drop unused SignalR extension to clear MessagePack CVE-2026-48109#329
mrostan wants to merge 1 commit into
mainfrom
mrostan/azure-drop-signalr-cve-2026-48109

Conversation

@mrostan

@mrostan mrostan commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

What & why

Today's vuln scan flagged a new fixable HIGH on latest-azure only:
CVE-2026-48109MessagePack 2.5.192 (out-of-bounds read / DoS in the LZ4 path).

The vulnerable MessagePack.dll isn't one of our deps — it's baked into Microsoft's
Azure Functions extension bundle. Its sole consumer is the SignalR Service extension
(verified against the bundle's function.deps.json reverse-dependency graph). Our Azure
Function app only uses HTTP + Durable Functions triggers — never SignalR — so the whole
SignalR assembly cluster is dead weight and MessagePack is reachable code we don't need.

Why delete, not patch the DLL

Docker Scout reports a .NET package only when both its deps.json entry and its DLL
exist on disk. I verified locally:

  • Overwriting MessagePack.dll with a patched 2.5.301 build → CVE still reported
    (Scout reads the version from the manifest, not the binary).
  • Deleting the DLL → CVE cleared.

So we delete the SignalR-cluster assemblies and de-register the extension. As a bonus this
removes ~6 unused libraries from the image's attack surface, retiring a recurring class of
bundle-CVE findings.

Changes

  • resources/azure/prune_signalr_extension.py — deletes the SignalR-cluster DLLs
    (MessagePack(.Annotations), Microsoft.Azure.SignalR.*, …SignalRService) from every
    bundle bin dir and de-registers SignalR from each extensions.json. Fails the build
    loudly
    if its targets aren't found (a future bundle restructure surfaces as a build error,
    not a silent no-op that lets the CVE back in). Bundle version dir is globbed → survives the
    pending python3.13 base bump.
  • Dockerfile.azure — the azure target extracted into its own file (it builds FROM
    Microsoft's Functions base and shares nothing with the python:3.12-slim base stage), with
    the prune wired in. Dockerfile keeps a pointer note; CI now uses -f Dockerfile.azure.
  • apollo/interfaces/azure/README.md — fixed the stale Dockerfile_az reference; documented
    the smoke test.
  • resources/azure/durable_smoke_test.sh — boots the built image against Azurite and runs a
    Durable Functions orchestration end-to-end.

Validation (local)

  • Scout on the built image: 0 MessagePack vulnerabilities; 0 SignalR/MessagePack DLLs remain.
  • Smoke test passes: host boots with no SignalR/MessagePack load errors, DurableTask loads on
    the AzureStorage backend, orchestration reaches Completed.

Notes

  • Image size is unchanged — deletion clears the scan (scanner reads the merged FS) but the
    base-layer bytes remain; reclaiming them would require flattening, which isn't worth the
    fragility here. The win is vuln/attack-surface reduction, not size.
  • Smoke test is intentionally not in CI. The prune's build-time fail-loud runs in both the
    merge-queue and dev-merge builds, and dev deployment exercises Durable Functions for real — so
    both regression modes are already covered. Run the smoke test locally before merging to dev and
    after any base-image change.

🤖 Generated with Claude Code

…26-48109

The Azure Functions base image bakes in the full extension bundle, whose
SignalR Service extension is the sole consumer of MessagePack (verified
against the bundle's function.deps.json reverse-dependency graph).
MessagePack 2.5.192 carries CVE-2026-48109 (HIGH). Our Azure Function app
only uses HTTP and Durable Functions triggers — never SignalR — so the
entire SignalR assembly cluster is dead weight and MessagePack is reachable
code we don't need.

Remove it rather than patching the DLL: Docker Scout reports a .NET package
only when BOTH its deps.json entry and its DLL exist on disk. Overwriting
MessagePack.dll with a patched build does NOT clear the finding (Scout reads
the version from the manifest, not the binary) — but deleting the DLL does.
So prune_signalr_extension.py deletes the SignalR-cluster assemblies and
de-registers the extension from every extensions.json, failing the build
loudly if the expected targets aren't found (so a future bundle restructure
can't silently let the CVE back in). The bundle version dir is globbed, so
this survives the base-image bundle bumps and the pending python3.13 move.

Also:
- Extract the azure target into its own Dockerfile.azure. Unlike the other
  targets it builds FROM Microsoft's Functions base and shares nothing with
  the python:3.12-slim `base` stage, so a separate file is clearer; CI now
  passes `-f Dockerfile.azure`. Fixes the stale `Dockerfile_az` README ref.
- Add resources/azure/durable_smoke_test.sh: boots the built image against
  Azurite and runs a Durable Functions orchestration end-to-end, asserting
  the host starts without SignalR and the durable runtime is healthy.

Verified locally: Scout reports 0 MessagePack vulnerabilities in the built
image, and the smoke test passes (orchestration reaches Completed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant