Safeguard
Developer Tools•

What does a plain version number mean in Cargo.toml?

In Cargo.toml, log = 1.2.3 is a caret requirement. See which versions it allows, why 0.x crates behave differently, and what that means for updates.

Safeguard Security Team
3 min read

In Cargo.toml, a bare version such as 1.2.3 is a caret requirement. It allows any SemVer compatible release from that version up, so 1.2.3 accepts anything from 1.2.3 up to, but not including, 2.0.0. Crates that start with 0 are stricter, which surprises many teams.

The rule in one sentence

The Cargo reference says default requirements specify a minimum version with the ability to update to SemVer compatible versions. Versions are compatible if their left most non zero component is the same. Leaving off the caret is exactly equivalent to writing it, so log = "^1.2.3" and log = "1.2.3" mean the same thing.

What each form allows

You writeIt means
1.2.3at least 1.2.3, below 2.0.0
1.2at least 1.2.0, below 2.0.0
1at least 1.0.0, below 2.0.0
0.2.3at least 0.2.3, below 0.3.0
0.2at least 0.2.0, below 0.3.0
0.0.3exactly the 0.0.3 line, below 0.0.4

The Cargo reference notes this differs from SemVer, which treats all pre 1.0.0 packages as incompatible with each other. Cargo treats a change in the minor number of a 0.x crate as the breaking boundary.

Why this matters for security

A requirement is not a pin. When you run cargo update, Cargo may move a dependency to any newer version the requirement allows. That is how a patched release reaches you without editing Cargo.toml, which is useful.

It also means the lockfile, not Cargo.toml, records what you actually build. Without a committed Cargo.lock, two builds a week apart can resolve different versions. See should a Rust service commit Cargo.lock.

Wide ranges can also hide a problem: a requirement like 0.2 may keep you on a vulnerable 0.2.x until you widen it to the fixed 0.3 line, and Cargo will not cross that boundary on its own.

What to do with it

  1. Keep Cargo.toml requirements reasonably loose for libraries, so downstream users can take patches.
  2. For applications, commit Cargo.lock and update deliberately.
  3. When an advisory says the fix is in a new minor of a 0.x crate, edit the requirement, because a plain update will not cross it.
  4. Use cargo update with a precise version for a single targeted bump, as explained in cargo update precise.
  5. Review lockfile changes in pull requests like code.

Exact pins

Cargo supports an exact requirement with an equals sign. Use it sparingly. It blocks automatic patch updates, so an advisory fix needs a manual edit.

Safeguard's dependency scanning reads Cargo manifests and lockfiles, so the resolved versions are what get checked. A free scan is available at gold.safeguard.sh/scan.

Quick check

Does 0.2.3 allow 0.3.0?

No. For 0.x crates the left most non zero component is the minor number, so 0.2.3 allows 0.2.3 up to below 0.3.0.

Is 1.2.3 the same as exactly 1.2.3?

No. It is a caret requirement that allows later compatible releases below 2.0.0. An exact pin needs an equals sign.

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.