Safeguard
Developer Tools•

Does .NET central package management change how I scan solutions?

Central package management moves NuGet versions to Directory.Packages.props. Learn what scanners must read, how nested files work and what pinning changes.

Safeguard Security Team
3 min read

Yes. With central package management, project files list packages without versions, and the versions live in Directory.Packages.props. A scanner that reads only each project file sees packages with no version. It must also read the props file closest to each project, or resolve through the build.

What the feature does

Microsoft's NuGet documentation says to create a Directory.Packages.props file at the root of the repository and set ManagePackageVersionsCentrally to true. Inside, PackageVersion elements name the packages and versions. In each project, PackageReference elements omit the Version attribute and the version comes from the props file.

<Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
  </PropertyGroup>
  <ItemGroup>
    <PackageVersion Include="PackageA" Version="1.0.0" />
  </ItemGroup>
</Project>

The nearest file wins

This is the part that trips up monorepo scans. The docs say only one Directory.Packages.props is evaluated for a given project by default, and the file closest to the project is the one used. A parent file is not merged automatically. You must import it by hand if you want its settings.

LayoutWhich props file applies
One file at repo rootAll projects
Root file plus a file in one solution folderProjects in that folder use the nearer file only
Nested file that imports its parentBoth sets of versions apply

If your scanner assumes one global file, it may report the wrong versions for projects under a nested file.

Overrides and pinning

Three features change which version you really ship:

  1. VersionOverride. A project can override a central version on one reference. This takes precedence. It can be disabled with a property, which is a good policy control.
  2. Transitive pinning. When enabled, a central entry can raise a transitive dependency without a top level reference. The docs say downgrades are not allowed and raise error NU1109.
  3. Different versions per target framework. Conditions can select a version by target framework, so one package can have two versions in one solution.

For scanning, the practical effect is that one package name can map to several shipped versions. Make sure your report lists the resolved version per project and target framework.

Fixing a finding

Central management helps remediation. To raise a vulnerable package, change one PackageVersion line, and every project that references it moves. Transitive pinning lets you raise a vulnerable transitive package without editing every project. Check for VersionOverride entries first, because they can keep an old version in one project after you fix the central file.

git grep -n "VersionOverride" -- '*.csproj'

Combine this with a lock file in CI, covered in NuGet lock files and locked mode, so the resolved graph is the same everywhere.

Safeguard scans NuGet dependencies and builds SBOMs per project. Try the free scan at https://gold.safeguard.sh/scan.

Try it yourself

Open the demo and look at how a finding is tied to a package version. Then ask whether your own scan shows the version from the props file.

Click through it at your own pace, or open it full screen.

Quick check

Where do versions live with central package management?

In Directory.Packages.props, as PackageVersion entries. Project files use PackageReference without a Version.

Are parent props files merged automatically?

No. The nearest file is used, and a parent must be imported manually.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.