Safeguard
Developer Tools•

How do you update one Rust crate without churning the whole SBOM?

Name the crate in cargo update for a conservative change, preview with a dry run, and compare SBOMs before and after to keep the diff small.

Safeguard Security Team
7 min read

Name the crate when you run cargo update, for example cargo update regex. Cargo then performs a conservative update: it changes that dependency, touches its transitive dependencies solely if it must, and leaves everything else locked. Add the dry run option first to preview, then compare SBOMs from before and after.

What the Cargo documentation says

The cargo update page states that the command updates dependencies in Cargo.lock to the latest versions, and creates the lockfile with the latest available versions if none exists. When you pass one or more package specs, a conservative update is performed. Just the specified dependency is updated, its transitive dependencies are updated solely if the spec cannot be updated without them, and all other dependencies remain locked at their currently recorded versions. With no spec, all dependencies are updated.

Three options matter for security work:

OptionWhat it does
preciseWith a spec, sets a specific version, or for a git dependency a revision such as a SHA or tag
recursiveWith a spec, forces the dependencies of that spec to update too
dry-runShows what would be updated without writing the lockfile

The page also notes that you can specify a yanked version with the precise option, though it is not recommended.

Why a small diff is a security feature

A reviewer can reason about three changed packages. Nobody can reason about sixty. When an advisory forces a fix, the safest change is the smallest one that removes the vulnerable version. A broad update mixes the fix with unrelated upgrades, which makes regressions harder to attribute and makes the SBOM diff noisy for anyone auditing it later.

A worked example

Suppose a service depends on a crate called parser, version 1.4.2, and an advisory says versions below 1.4.5 are affected. The names and versions are invented for this illustration.

  1. Generate an SBOM from the current commit and save it as before.
  2. Run cargo update parser with the dry run option. The output lists the planned change: parser moves to 1.4.5, and one transitive helper crate moves one patch version because parser 1.4.5 needs it.
  3. Run the same command without the dry run option.
  4. Build and test.
  5. Generate an SBOM and save it as after.
  6. Diff the two files. Expect exactly two changed components. If you see more, find out why before merging.

The diff is your evidence. It shows the vulnerable version leaving and the fixed version arriving, with nothing else changing.

When the conservative update is not enough

Sometimes the spec cannot be updated without updating others. Cargo then updates the needed transitive dependencies, as the docs describe. Read the dry run output carefully in that case. If it wants to move a package that your team pinned for a reason, stop and talk to its owner.

The recursive option is the opposite tool. It forces the dependencies of the spec to update as well, which can be useful when a vulnerable crate sits underneath the one you named. Use it deliberately, and expect a larger diff.

Git dependencies

For a crate pulled from git, the precise option accepts a revision. That lets you move from one commit to a specific newer one. Record the old and new hashes in the pull request, and check upstream that the new commit contains the fix. Cargo.lock keeps the exact revision in the package source field, so the lockfile diff shows the change.

Guarding the process in CI

The cargo update docs describe a locked flag that asserts the exact same dependencies and versions are used as when the lockfile was generated. Cargo exits with an error if the lock file is missing or if it would have to change the lockfile because of a different resolution. Run builds with that flag in CI so nobody ships a tree that resolved differently from the committed lockfile, and generate the SBOM after that step.

A review checklist

  1. Does the pull request change Cargo.lock and nothing else, unless the manifest had to change?
  2. Does the SBOM diff list solely the packages you expected?
  3. Is the fixed version at or above the advisory's patched version?
  4. Did any package change source, for example from registry to git?
  5. Did tests and the build pass with the locked flag?
  6. Is the advisory reference in the pull request description?

Putting it into a routine

When a new advisory affects a crate you use, search your stored SBOMs for the version, open a branch, run the conservative update, and attach the SBOM diff. Teams that do this routinely turn a stressful day into a fifteen minute task. Safeguard can scan SBOMs and dependencies and use reachability analysis to help you decide which advisories are worth that branch first, and the free scan at gold.safeguard.sh/scan is a quick way to try it on a Rust project.

Mistakes to avoid

Running a bare cargo update to fix one advisory. It updates all dependencies, which is exactly the broad change you wanted to avoid. Another mistake is skipping the SBOM before step, then having nothing to diff against. Save a baseline file at the start of every dependency change, even a small one.

A third mistake is merging without a build. A conservative update still changes code you ship, and a patch release can behave differently. Run your tests, and if your project has integration tests that touch the updated crate, run those first.

What to write in the pull request

Keep the description short and factual: the advisory identifier, the old and new versions, the command you ran, a note that the dry run showed the expected change, and a pointer to the SBOM diff. Reviewers who see this can approve in minutes. Months later, an auditor can see exactly why the lockfile changed and what evidence existed at the time.

When to batch updates

Not every update needs its own branch. Routine refreshes, with no advisory behind them, can be grouped on a schedule, for example monthly. Keep urgent security fixes separate so they can ship fast and be reverted independently. The SBOM diff makes both kinds easy to review, because it lists changes in plain terms.

Try it yourself

Click through it at your own pace, or open it full screen.

Look at how a finding with a known fixed version turns into a specific, small upgrade.

Quick check

What does cargo update with a package name change?

It performs a conservative update: that dependency moves, its transitive dependencies move solely if needed, and everything else stays locked.

How do I preview an update without changing Cargo.lock?

Use the dry run option. It displays what would be updated without writing the lockfile.

Can I update a git dependency to a specific commit?

Yes. With a spec, the precise option accepts a git revision such as a SHA hash or tag.

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.