In NuGet a plain version such as 6.1 means that version or higher, resolving to the smallest acceptable one. Square brackets pin exactly, and a star floats to the highest match. Microsoft advises against upper bounds on packages you do not own unless you know of a compatibility problem.
The notation
NuGet documents interval notation for ranges and shows how each resolves. The table pairs a few common forms with what they mean.
| Written as | Meaning | Resolves to |
|---|---|---|
| 6.1 | 6.1 or higher | Smallest acceptable stable version |
| 6.* | Any 6.x.y | Highest acceptable stable version |
| [6.1.0] | Exactly 6.1.0 | That version |
| (4.1.3,) | Above 4.1.3 | Smallest acceptable stable version |
| [1.3.2,1.5) | 1.3.2 up to but not including 1.5 | Smallest acceptable stable version |
The surprise is the first row. Most people read a plain version as a pin, but NuGet treats it as a lower bound and then picks the lowest version that works. That is stable, and it also means you will not get a newer patch just because it exists.
The one that floats
A star is a floating version. It picks the highest match every time it resolves, so two restores on different days can differ. If you float, you need a lock file, or the build is no longer repeatable. Floating on a package you do not control also lets a brand new release into your build with no pull request.
Upper bounds
NuGet's best practice says to always specify a version or range for dependencies in project files, packages.config and nuspec files, because without one, consistent restore results are not guaranteed. It also says to avoid upper bounds on packages you do not own unless you know of a compatibility problem, because upper bounds harm adoption, discourage consumers from getting valuable updates, and can lead them to unsupported versions.
That advice is aimed at package authors most of all. If you publish a library with a tight upper bound on a dependency, every consumer who needs a newer version of that dependency gets a conflict.
Choosing, by situation
- For an application you ship, use a plain minimum version and enable lock files with locked mode in CI. You get repeatability and reviewed updates.
- For a package you publish, state the lowest version you tested and leave off the upper bound unless you know of a real break.
- For a package that must not change, use an exact bracket pin.
- For anything floating, use a lock file and keep it out of release builds unless you mean it.
- To keep a known bad version out, prefer a lower bound above it, such as a range that starts just after the vulnerable release.
Reading the result
Do not guess what your project resolved. List it, and compare with what you intended.
dotnet list package --include-transitive
Where Safeguard fits
Safeguard's dependency scanning and SBOM generation can show the packages your .NET project resolves and which known vulnerabilities affect them, and a free scan is at gold.safeguard.sh/scan.
Quick check
Is Version="1.0" a pin in NuGet?
No. It means 1.0 or higher, and NuGet resolves to the smallest acceptable stable version. Use square brackets for an exact pin.
Should my published package cap its dependency versions?
Microsoft advises against upper bounds on packages you do not own unless you know of a compatibility problem, since they block consumers from updates.
Sources
Last reviewed: 19 October 2026.