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 as | Resolves 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
- Application with a release process: use fixed versions plus a lock file.
- Internal tool where drift is acceptable: floating with a lock file is workable.
- Library you publish: avoid floating, because consumers cannot see or control it.
- 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
- NuGet package dependency resolution, Microsoft Learn
- NuGet PackageReference in project files, Microsoft Learn
Last reviewed: 19 October 2026.