Safeguard
Developer Tools•

Do NuGet floating versions make your builds unsafe?

Floating versions like 6.0.* let NuGet pick the newest match on restore. That helps patching but hurts repeatability. Learn the trade and how to limit it.

Safeguard Security Team
3 min read

Floating versions are not unsafe by themselves, but they make builds less repeatable. A version such as 6.0.* tells NuGet to take the highest matching version on every restore, so two builds of the same commit can differ. Pair floating with a lock file, or avoid it.

What a floating version is

In a PackageReference you can write a wildcard instead of a fixed version. Microsoft's dependency resolution page gives examples.

Written asResolves to
6.0.*Highest stable 6.0.x
4.*Highest stable 4.x
*Highest stable version
1.1.*-*Highest 1.1.x, including prerelease

Floating versions can be specified only at the project level, not inside a package's own dependency ranges.

The upside

You pick up patch releases without editing a file. For security fixes inside a minor line, that sounds attractive. The package is updated the next time anyone restores.

The downside

  • Two developers restoring on different days can compile against different code.
  • A compromised or buggy release is pulled in automatically, with no pull request to review.
  • Builds are harder to reproduce when an incident needs to be investigated.
  • The version in your SBOM at release time may not match what a rebuild produces.

A fresh release that matches the pattern flows into production the next time CI restores, which is also how a malicious publish on a floating range reaches you quickly. That is a reason to prefer reviewed updates.

Containing the risk

Microsoft recommends enabling the lock file when you use floating versions. With RestorePackagesWithLockFile set, restore writes packages.lock.json, and later restores use it instead of re-evaluating. To pick up a newer matching version on purpose, run restore with the force evaluate option.

dotnet restore --use-lock-file
dotnet restore --locked-mode          # CI: fail if the graph would change
dotnet restore --force-evaluate       # deliberate refresh

A cleaner pattern for many teams is to drop floating ranges and let an automated update process open reviewed pull requests. You still get fast patching, with a diff and a build before it ships.

A short decision guide

  1. Application with a release process: use fixed versions plus a lock file.
  2. Internal tool where drift is acceptable: floating with a lock file is workable.
  3. Library you publish: avoid floating, because consumers cannot see or control it.
  4. Anything compliance sensitive: fixed versions, locked mode in CI, and a record of each update.

Try it yourself

Click through it at your own pace, or open it full screen. Look at how changes in dependencies are noticed after the fact, which is what a floating range makes necessary.

Safeguard's dependency scanning and SBOM generation record the versions actually resolved, and you can try a free scan.

Quick check

Does a lock file stop floating versions from updating forever?

No. It freezes the resolved graph until you ask for a re-evaluation, for example with force evaluate.

Can a package author use a floating range in a dependency?

No. Per Microsoft, floating versions can be specified only at the project level.

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.