Skip to content

[AppSec] Add packages.lock.json files for dependency locking#7725

Draft
aikido-autofix[bot] wants to merge 3 commits into
mainfrom
fix/security-dotnet-40388333-pt2b
Draft

[AppSec] Add packages.lock.json files for dependency locking#7725
aikido-autofix[bot] wants to merge 3 commits into
mainfrom
fix/security-dotnet-40388333-pt2b

Conversation

@aikido-autofix
Copy link
Copy Markdown
Contributor

@aikido-autofix aikido-autofix Bot commented May 27, 2026

.NET Lockfile Creation

This PR adds packages.lock.json files to ensure reproducible builds and secure dependency management.

Benefits:

  • Reproducible builds: Locked dependency versions ensure consistent builds across environments
  • Security: Prevents supply chain attacks by pinning specific dependency versions
  • Performance: Faster builds in CI/CD pipelines
  • Deterministic child dependency scanning: Scanning for child dependencies becomes deterministic, reducing false positives in dependency analysis

The lockfiles were generated using dotnet restore command.

@aikido-autofix aikido-autofix Bot requested review from a team as code owners May 27, 2026 13:30
@aikido-autofix aikido-autofix Bot added the ai-review Request a Claude code review label May 27, 2026
@aikido-autofix aikido-autofix Bot requested review from a team as code owners May 27, 2026 13:30
@codecov
Copy link
Copy Markdown

codecov Bot commented May 27, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 65.01%. Comparing base (705995d) to head (bac291a).
⚠️ Report is 7 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7725      +/-   ##
==========================================
+ Coverage   60.55%   65.01%   +4.46%     
==========================================
  Files        2142     2145       +3     
  Lines       94847    95028     +181     
  Branches     8487     8504      +17     
==========================================
+ Hits        57430    61786    +4356     
+ Misses      35401    31126    -4275     
- Partials     2016     2116     +100     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@withinfocus withinfocus marked this pull request as draft May 27, 2026 15:18
@withinfocus
Copy link
Copy Markdown
Contributor

withinfocus commented May 27, 2026

Testing Aikido and it doesn't have a draft mode -- hang tight!

…props

Apply the lockfile-restore setting solution-wide via Directory.Build.props
instead of repeating it in every csproj. Inheritance covers the whole
solution, so the setting now applies to all current and future projects
uniformly.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 27, 2026

🤖 Bitwarden Claude Code Review

Overall Assessment: REQUEST CHANGES

This PR adds packages.lock.json files across the solution and promotes RestorePackagesWithLockFile=true to Directory.Build.props to deliver reproducible restores, supply-chain pinning, and deterministic dependency scanning. The previous review flagged eight projects with no lock file; the latest commit ("Try to force a lock generation, at least partially") adds files for those projects but commits them as empty stubs that do not lock any dependencies, so the PR's stated benefits are not realized for five production services (Admin, Identity, Events, EventsProcessor, Scim) and three utility projects (RustSdk, SeederApi, Server). A new src/Sql/packages.lock.json was also added for a .sqlproj that does not use NuGet PackageReferences.

Code Review Details
  • ⚠️ : Nine packages.lock.json files committed as empty stubs — no dependencies locked; PR goals unmet for Admin, Identity, Events, EventsProcessor, Scim, RustSdk, SeederApi, Server, and an unnecessary file added for the SQL project.
    • Directory.Build.props:15

Dependency Changes

No package version changes — this PR only adds lock files and a solution-wide MSBuild property.

Comment thread Directory.Build.props
<Nullable Condition="'$(Nullable)' == '' and '$(IsTestProject)' != 'true'">enable</Nullable>
<TreatWarningsAsErrors Condition="'$(TreatWarningsAsErrors)' == ''">true</TreatWarningsAsErrors>
<NuGetAuditLevel>critical</NuGetAuditLevel>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
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.

⚠️ IMPORTANT: Eight projects under this solution-wide setting are missing packages.lock.json and will not gain reproducible-restore or deterministic dependency-scan coverage.

Details and fix

RestorePackagesWithLockFile=true here applies to every project that inherits from this Directory.Build.props (no Directory.Build.targets or per-project override exists). The PR added 49 lock files but the repo contains 57 csproj files; the following 8 projects have no packages.lock.json:

  • src/Admin/Admin.csproj
  • src/Identity/Identity.csproj
  • src/Events/Events.csproj
  • src/EventsProcessor/EventsProcessor.csproj
  • bitwarden_license/src/Scim/Scim.csproj
  • util/RustSdk/RustSdk.csproj
  • util/SeederApi/SeederApi.csproj
  • util/Server/Server.csproj

A NuGet lock file locks the direct + transitive graph of its own project — referencing Core from a covered project does not transitively lock Admin's closure. The PR description's stated benefits ("Reproducible builds", "Prevents supply chain attacks by pinning specific dependency versions", "Deterministic child dependency scanning") are therefore not realized for these projects, several of which are production services (Admin, Identity, Events, EventsProcessor, Scim).

In addition, with the setting enabled solution-wide, the next dotnet restore on a clean checkout will silently generate these missing lock files locally, leaving the working tree dirty.

Fix: run dotnet restore against each of the 8 projects and commit the generated packages.lock.json files alongside the 49 already added.

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.

Yep, Aikido Endpoint Protection ...

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.

@claude apply this suggestion by running dotnet restore against the entire solution

Copy link
Copy Markdown
Contributor

@claude claude Bot May 27, 2026

Choose a reason for hiding this comment

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

Claude finished @withinfocus's task in 2m 36s —— View job


Cannot Run dotnet restore in This Environment

I attempted to run dotnet restore bitwarden-server.slnx to generate the 8 missing packages.lock.json files, but the dotnet binary is not in the allowed tool list for this Claude Code action. Each invocation returns This command requires approval and the runtime blocks it.

  • Verify the 8 missing projects (Admin, Identity, Events, EventsProcessor, Scim, RustSdk, SeederApi, Server)
  • Run dotnet restore against the solutionblocked: dotnet not in allowed_tools
  • Verify the 8 missing packages.lock.json files were generated
  • Commit and push the new lock files

How to unblock:

Either:

  1. Run locally and push (recommended — produces hash-verified lock files):

    git fetch origin fix/security-dotnet-40388333-pt2b
    git checkout fix/security-dotnet-40388333-pt2b
    dotnet restore bitwarden-server.slnx
    git add src/Admin/packages.lock.json src/Identity/packages.lock.json \
            src/Events/packages.lock.json src/EventsProcessor/packages.lock.json \
            bitwarden_license/src/Scim/packages.lock.json \
            util/RustSdk/packages.lock.json util/SeederApi/packages.lock.json util/Server/packages.lock.json
    git commit -m "fix(security): add missing packages.lock.json files"
    git push
  2. Update the reusable workflow at bitwarden/gh-actions/.github/workflows/_respond.yml to extend allowed_tools (or claude_args) with Bash(dotnet restore:*), then re-run @claude apply this suggestion ….

Lock files cannot be hand-authored — they contain content hashes from the NuGet feed that only the restore process can compute correctly, so I can't substitute another approach from here.
· Branch: fix/security-dotnet-40388333-pt2b

Comment thread Directory.Build.props
<Nullable Condition="'$(Nullable)' == '' and '$(IsTestProject)' != 'true'">enable</Nullable>
<TreatWarningsAsErrors Condition="'$(TreatWarningsAsErrors)' == ''">true</TreatWarningsAsErrors>
<NuGetAuditLevel>critical</NuGetAuditLevel>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
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.

⚠️ IMPORTANT: Nine packages.lock.json files are committed as empty stubs ("net10.0": {}) — no dependencies are actually locked.

Details and fix

The latest commit ("Try to force a lock generation, at least partially") added lock files to the projects called out in the earlier review, but the resulting files contain no locked dependencies:

  • src/Admin/packages.lock.json (5 lines)
  • src/Identity/packages.lock.json (5 lines)
  • src/Events/packages.lock.json (5 lines)
  • src/EventsProcessor/packages.lock.json (5 lines)
  • bitwarden_license/src/Scim/packages.lock.json (5 lines)
  • util/RustSdk/packages.lock.json (5 lines)
  • util/SeederApi/packages.lock.json (5 lines)
  • util/Server/packages.lock.json (5 lines)
  • src/Sql/packages.lock.json (5 lines) — new

Compare with siblings that were properly restored: src/Api/packages.lock.json is 1,238 lines, src/SharedWeb/packages.lock.json is 1,398 lines, bitwarden_license/src/Sso/packages.lock.json is 1,202 lines. All of the affected projects pull in Microsoft.NET.Sdk.Web and/or Bitwarden.Server.Sdk plus several ProjectReferences, so their lock files should contain hundreds of resolved entries — not zero.

With RestorePackagesWithLockFile=true set solution-wide and these stubs in place, the next clean restore will either regenerate them (leaving the working tree dirty) or, in CI with --locked-mode, fail because the actual dependency graph does not match the empty lock. The PR description's stated benefits (reproducible builds, supply chain pinning, deterministic dependency scanning) are not realized for these projects — five of which are production services (Admin, Identity, Events, EventsProcessor, Scim).

Separately, src/Sql/Sql.sqlproj is a SQL Database project (Microsoft.Build.Sql SDK) with no PackageReference items — it does not participate in NuGet lock file generation. Adding src/Sql/packages.lock.json is incorrect and should be removed.

Fix: regenerate the eight .csproj lock files via a real dotnet restore (in an environment that can resolve the full graph for each project — Admin/Scim need the OSS configuration consideration since their conditional ProjectReferences depend on it) and delete src/Sql/packages.lock.json.

@sonarqubecloud
Copy link
Copy Markdown

@withinfocus withinfocus changed the title [AppSec] Add 49 packages.lock.json files for dependency locking [AppSec] Add packages.lock.json files for dependency locking May 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review Request a Claude code review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant