Skip to content

Pin vulnerable transitive packages and audit them in CI (#650) - #654

Merged
erikdarlingdata merged 3 commits into
devfrom
fix/650-transitive-pins
Oct 14, 2026
Merged

erikdarlingdata merged 3 commits into
devfrom
fix/650-transitive-pins

Conversation

@erikdarlingdata

@erikdarlingdata erikdarlingdata commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

Claude posting for Erik Darling.

Pins the two vulnerable transitive packages, makes high-severity transitive reports fail the build, and adds a dependency-submission workflow so Dependabot gets a graph with real versions.

Files changed

  • Directory.Packages.props: System.Security.Cryptography.Pkcs 10.0.13 and MessagePack 2.5.307, each with a comment naming Pin System.Security.Cryptography.Pkcs and MessagePack over vulnerable transitive versions, and make Dependabot see transitive packages #650 and when to drop it.
  • src/PlanViewer.Core/PlanViewer.Core.csproj: direct PackageReference to Pkcs.
  • src/PlanViewer.Ssms/PlanViewer.Ssms.csproj: direct PackageReference to MessagePack with ExcludeAssets="runtime", like the SDK reference above it: SSMS supplies MessagePack at run time and the extension must never carry its own copy. Without the exclude, the pin copied MessagePack.dll and MessagePack.Annotations.dll into the output.
  • Directory.Build.props (new, repo root): NuGetAuditMode=all and WarningsAsErrors += NU1903.
  • src/Directory.Build.props: now imports the root file. MSBuild uses only the nearest Directory.Build.props, so without this import the root file would never reach anything under src/ (the root file reaches tests/ and server/ directly). Found while checking the gate; see acceptance.
  • .github/workflows/ci.yml: added root Directory.Build.props to the code path filter (the filter listed only src/Directory.Build.props, so a change to the audit settings alone would have skipped the build).
  • .github/workflows/dependency-submission.yml (new): see below.

Resolved versions

  • Pkcs: 10.0.13 in Core, App, Cli and Core.Tests (checked in each project.assets.json). Only PlanViewer.Core needed the direct reference; NuGet nearest-wins carried it through the project references. Web and PlanShare were already clean.
  • MessagePack: 2.5.307 in src/PlanViewer.Ssms/obj/project.assets.json. No newer Microsoft.VisualStudio.SDK exists (17.14.40265 is the newest 17.x on nuget.org), so I pinned rather than bumped.

Acceptance

  • dotnet list PlanViewer.sln package --vulnerable --include-transitive: every project prints "has no vulnerable packages" (Core, App, Cli, Web, Core.Tests). PlanShare (not in the sln) checked separately, also clean.
  • dotnet build PlanViewer.sln -c Debug: 0 Warning(s), 0 Error(s), no NU1902 or NU1903.
  • Gate proven: with the Core Pkcs reference removed, building PlanViewer.Cli fails with error NU1903: Warning As Error ... System.Security.Cryptography.Pkcs 9.0.18, and NU1902 stays a warning. Restored afterwards.
  • SSMS: MSBuild.exe src/PlanViewer.Ssms/PlanViewer.Ssms.csproj -restore -t:Build -p:Configuration=Release -p:DeployExtension=false exit 0, 0 errors, 0 warnings, VSCT errors = 0 (the VSSDK targets come from the BuildTools package). PlanViewer.Ssms.Installer (net472, Release) and PlanViewer.Ssms.Installer.Tests (Release) build with 0 errors, 0 warnings. InstallSsmsExtension.exe was not run. server/PlanShare Debug builds clean.
  • dotnet test --project tests/PlanViewer.Core.Tests -c Debug: total 1499, failed 0.

Follow-up corrections

  • MessagePack runtime excluded. After deleting src/PlanViewer.Ssms/bin and obj and rebuilding with the same MSBuild recipe (exit 0, 0 errors, 0 warnings): (a) no MessagePack*.dll anywhere under bin; (b) obj/project.assets.json still contains "MessagePack/2.5.307"; (c) the .vsix contains only PlanViewer.Ssms.dll among its DLLs.
  • dependency-submission.yml steps added: Install WASM workload (dotnet workload install wasm-tools, as ci.yml does) before Restore solution, and Add MSBuild to PATH (microsoft/setup-msbuild v3.0.0, same pin as release.yml) before Restore SSMS projects. Order: checkout, setup-dotnet, workload, restore solution, setup-msbuild, restore SSMS projects, submit.
  • dotnet build PlanViewer.sln -c Debug after the edits: no warning NU or error lines.

Judgment calls and notes

  • NU1902 (moderate) is deliberately not an error; the brief and issue name only NU1903.
  • Dependency submission runs on windows-latest so the old-format SSMS project can be restored with msbuild -t:Restore (the component detector reads project.assets.json). The action is advanced-security/component-detection-dependency-submission-action v0.2.0 (latest release), pinned to commit a02aeda7a175ad4dd38a13c4d3ff2df9da8f2cf0. I could not run this workflow locally; its first real run is the push of this branch's merge to dev, and it is the one piece not verified.
  • Dependabot alerts read the default branch, so transitive alerts start after the next dev to main release merge; the dev trigger is for exercising the workflow earlier. .github/dependabot.yml is unchanged.
  • src/Directory.Build.props comment corrected: PlanViewer.Ssms does import this file (through Microsoft.Common.props), which is how it gets the audit settings; it just does not generate assembly attributes from <Version>, so the manual version bump advice stands.

Review round 1

  • F1: the audit gate now fails on NU1904 (critical) as well as NU1903 (high). WarningsAsErrors is NU1903;NU1904 in the root Directory.Build.props, with a comment naming the emergency override -p:NuGetAudit=false.
  • F2: dependency-submission.yml checkout uses persist-credentials: false, and the header says to drop dev from the push trigger once the first dev run is green (dev snapshots feed no alerts; each run holds a contents: write token while running a downloaded binary).
  • F4: every restore in dependency-submission.yml (solution, both installers, the msbuild -t:Restore) passes -p:NuGetAudit=false, with a comment: a failed restore would leave the graph stale exactly when an alert is needed.
  • F5: the submit step sets fail-on-empty: 'true', so an empty scan cannot replace the graph.
  • F7: the Pkcs comment in Directory.Packages.props now says the drop condition is Pkcs 9.0.21 or later (10.0.13 or later on 10.x), and that the desktop app's self-contained publish takes Pkcs from the ASP.NET Core runtime pack, which the audit never sees.
  • F9: Directory.Build.props added to the path filters of deploy-planshare.yml, deploy-web.yml and ssms-installer-tests.yml (the last also gets src/Directory.Build.props).
  • F10: the release.yml SSMS step tees the msbuild output to a log and emits ::warning::SSMS restore failed the NuGet audit: <line> if it contains NU1903 or NU1904. Exit code behavior is unchanged. The Select-String snippet was tested against a fake log line.

NU1904 proof: a scratch project restoring System.Text.Encodings.Web 4.5.0 (with the repo-wide package version management turned off for it) failed with error NU1904: Warning As Error: Package 'System.Text.Encodings.Web' 4.5.0 has a known critical severity vulnerability, exit 1. The folder was deleted. dotnet build PlanViewer.sln -c Debug: 0 warnings, 0 errors. The five touched workflow files parse as YAML (PyYAML present).

Closes #650

🤖 Generated with Claude Code

https://claude.ai/code/session_018MrD9SGvLFx4kJaeGZyXG9

erikdarlingdata and others added 2 commits October 14, 2026 19:20
Pin System.Security.Cryptography.Pkcs 10.0.13 (via PlanViewer.Core) and
MessagePack 2.5.307 (via PlanViewer.Ssms) over the transitive versions,
audit transitive packages with NU1903 as an error, and submit the resolved
dependency graph to GitHub.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018MrD9SGvLFx4kJaeGZyXG9
…Pkcs drop condition

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018MrD9SGvLFx4kJaeGZyXG9
@erikdarlingdata
erikdarlingdata marked this pull request as ready for review October 14, 2026 23:54
@claude

claude Bot commented Oct 14, 2026

Copy link
Copy Markdown

Reviewed the build, props and workflow changes. I found nothing blocking.

  • Props chain: the GetPathOfFileAbove import in src/Directory.Build.props starts from src/.., so it resolves to the repo-root file. WarningsAsErrors is set before the version block and the existing NoWarn (which already has its comment).
  • No version bump: the Ssms vsixmanifest and AssemblyInfo.cs don't need touching.
  • Workflow: actions are pinned by SHA, persist-credentials: false is set, and restores skip the audit so the graph doesn't go stale.
  • Residual risk (Low): the component-detection action downloads a binary at run time while holding contents: write. The header comment already says to drop the dev trigger once the first run is green; I'd do that promptly.
  • Test coverage: this is build and CI configuration only, so the lack of new unit tests is fine. The first run of dependency-submission.yml is still unverified, as the description says.

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