Skip to content

Beamable.Microservice.SourceGen leaks Roslyn 4.0.0 as a runtime dependency: phantom CVE warnings and ~19 MB of compiler DLLs in every C#MS Docker image #4829

Description

@mhijaziB

Problem

Beamable.Microservice.SourceGen is an analyzer package, but its nuspec declares regular runtime dependencies:

<dependency id="Microsoft.CodeAnalysis.CSharp" version="4.0.0" />
<dependency id="Microsoft.CodeAnalysis.CSharp.Workspaces" version="4.0.0" />
<dependency id="System.Text.Json" version="9.0.0" />

That happens because templates/MicroserviceSourceGen/MicroserviceSourceGen/MicroserviceSourceGen.csproj references those packages without PrivateAssets="all". The standard guidance for source generators is that Roslyn references never flow to consumers; the compiler already provides them.

Two consequences for every customer microservice:

1. Phantom vulnerability warnings. The Roslyn 4.0.0 graph pulls Humanizer.Core 2.2.0, which pulls NETStandard.Library 1.6.1, which pulls System.Net.Http 4.3.0 (CVE-2018-8292) and System.Text.RegularExpressions 4.3.0 (CVE-2019-0820). Those are type-forwarding facades that never execute on .NET 8+, but Rider's Checkmarx-based inspection flags them red. Barnstorm reported exactly this on 2 Sep 2026.

Beamable.Microservice.SourceGen
└── Microsoft.CodeAnalysis.CSharp.Workspaces 4.0.0
    └── Humanizer.Core 2.2.0
        └── NETStandard.Library 1.6.1
            ├── System.Net.Http 4.3.0
            └── System.Text.RegularExpressions 4.3.0

2. Docker image bloat. Because Beamable.Microservice.Runtime.props sets CopyLocalLockFileAssemblies=true, the whole Roslyn graph gets copied into the service publish output, and the Dockerfile copies bin/beamApp/support wholesale into the image.

Measured on a minimal net10.0 service against the local 0.0.123.15 packages:

Template reference DLLs in output Output size
Current (OutputItemType="Analyzer" only) 65 35 MB
With IncludeAssets="analyzers;build" PrivateAssets="all" 54 16 MB

The analyzer was passed to csc identically in both builds (same 99 analyzer DLLs, MicroserviceSourceGen.dll present), so the filter changes nothing about code generation.

Fix

Two halves, and we want both:

  1. Package side. In the SourceGen csproj, mark Microsoft.CodeAnalysis.CSharp, Microsoft.CodeAnalysis.CSharp.Workspaces and System.Text.Json with PrivateAssets="all" so the published nuspec has no dependencies. This fixes every existing customer project on their next CLI upgrade without a csproj edit.
  2. Template side. In cli/beamable.templates/templates/BeamService/BeamService.csproj (and the Zone variant), change the SourceGen reference to OutputItemType="Analyzer" IncludeAssets="analyzers;build" PrivateAssets="all". This protects against the same regression if a dependency is ever added back, and it is the line we can tell existing customers to paste today.

Separate but related: the package also ships Microsoft.CodeAnalysis*.dll inside analyzers/dotnet/cs/. Shipping the compiler's own assemblies as analyzers is a known way to get assembly-load conflicts inside the IDE. Not the subject of this issue, but whoever touches the csproj should look at the $(OutputPath)\*.dll pack glob.

Proof to close

  • The nuspec inside the built Beamable.Microservice.SourceGen nupkg has an empty <dependencies> block.
  • dotnet nuget why <service>.csproj Microsoft.CodeAnalysis.CSharp on a fresh service reports no dependency.
  • bin/beamApp/support of a published service contains no Microsoft.CodeAnalysis*.dll or Humanizer.dll.
  • Callable generation, federation validation and the code fixers still work in Rider and VS on a fresh beam project new service.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions