Use GlobalPackageReference in Directory.Packages.props. It adds a package to every project in the repository as a development only dependency, with its assets kept private so they do not flow to your consumers. It needs central package management and tooling from 2022: NuGet 6.4, .NET SDK 7.0.100 preview 7, or Visual Studio 2022 17.4.
What it is
Microsoft describes a global package reference as a way to say that a package is used by every project in a repository. Typical uses are versioning tools, packages that extend the build, and analyzers needed everywhere. NuGet adds it to the PackageReference group with two pieces of metadata.
| Metadata | Value | Effect |
|---|---|---|
| IncludeAssets | Runtime, Build, Native, contentFiles, Analyzers | Used as a development dependency, not as a compile time reference |
| PrivateAssets | All | Not picked up by downstream dependencies |
Steps
- Enable central package management with a Directory.Packages.props at the repository root.
- Add a GlobalPackageReference item with an exact version.
- Remove duplicate per project references to the same package.
- Restore and build, then review any new warnings.
- Commit the change and add a reviewer rule for edits to this file.
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<GlobalPackageReference Include="Contoso.Analyzers" Version="1.2.3" />
</ItemGroup>
</Project>
Contoso.Analyzers is a placeholder for the real package ID you choose.
Why this helps security
- One place to pin the version of a build time package, so projects cannot drift.
- Analyzer coverage is the same everywhere, including new projects.
- A single pull request changes the whole repository, which is easy to review.
- Private assets stop the analyzer leaking into packages you publish.
Cautions
- A global package reference runs in every project, so a compromised package affects all of them. Review the publisher and contents before adding, as you would for any build time dependency.
- Keep versions exact, not floating.
- Include it in dependency scanning and your SBOM.
- Remember the built in SDK analyzers need no package. Adding the Microsoft.CodeAnalysis.NetAnalyzers package turns the built in ones off for projects targeting .NET 5 or later, and you should not also set EnableNETAnalyzers in that case.
- If a project needs to opt out, set up a deliberate exception, and keep the list short.
How it interacts with audit
NuGet Audit still checks these packages. A development only package with an advisory will produce the same warnings, so you can see and fix it like any other dependency.
Try it yourself
Click through it at your own pace, or open it full screen. Imagine each finding appearing the same way across every project once an analyzer is global.
Safeguard offers code scanning and dependency scanning that work across repositories, and a free scan is a fast first look.
Quick check
Does a global package reference require central package management?
Yes. It is declared in Directory.Packages.props alongside ManagePackageVersionsCentrally.
Will the analyzer flow into packages I publish?
No. PrivateAssets set to all prevents it from being picked up by downstream dependencies.
Sources
Last reviewed: 19 October 2026.