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 write | It means |
|---|---|
| 1.2.3 | at least 1.2.3, below 2.0.0 |
| 1.2 | at least 1.2.0, below 2.0.0 |
| 1 | at least 1.0.0, below 2.0.0 |
| 0.2.3 | at least 0.2.3, below 0.3.0 |
| 0.2 | at least 0.2.0, below 0.3.0 |
| 0.0.3 | exactly 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
- Keep Cargo.toml requirements reasonably loose for libraries, so downstream users can take patches.
- For applications, commit Cargo.lock and update deliberately.
- 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.
- Use
cargo updatewith a precise version for a single targeted bump, as explained in cargo update precise. - 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.