Safeguard
Developer Tools•

NuGet version ranges: when to float, pin or set an upper bound

In NuGet a plain version is a minimum, brackets pin and a star floats. See what each resolves to and why upper bounds on others' packages are discouraged.

Safeguard Security Team
4 min read

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 asMeaningResolves to
6.16.1 or higherSmallest acceptable stable version
6.*Any 6.x.yHighest acceptable stable version
[6.1.0]Exactly 6.1.0That version
(4.1.3,)Above 4.1.3Smallest acceptable stable version
[1.3.2,1.5)1.3.2 up to but not including 1.5Smallest 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

  1. 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.
  2. For a package you publish, state the lowest version you tested and leave off the upper bound unless you know of a real break.
  3. For a package that must not change, use an exact bracket pin.
  4. For anything floating, use a lock file and keep it out of release builds unless you mean it.
  5. 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.

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.