Safeguard
Supply Chain•

Does turning off default features in Cargo reduce attack surface?

Turning off default features can remove code, but Cargo unifies features across the graph. How it works, resolver 2 and how to verify the result.

Safeguard Security Team
3 min read

It can, but not reliably. Setting default-features = false stops your crate from requesting a dependency's defaults, yet Cargo builds each dependency once with the union of all features any package asks for. If another crate in the graph wants the defaults, they come back.

Definitions

A feature is an optional part of a crate, switched on by name. Default features are the set enabled when you do not say otherwise. Feature unification is Cargo's rule of building a dependency once, with every feature requested by anyone in the graph.

What the documentation says

The Cargo reference states that defaults can be disabled with the false setting, then notes this does not guarantee they stay off, because another package may depend on the same crate with defaults enabled. It also says features are meant to be additive: enabling a feature should not remove functionality.

Resolver 2

Setting resolver = "2" changes unification in three ways:

CaseWith resolver 2
Platform specific dependencies for targets you are not buildingTheir features are ignored
Build dependencies and proc macrosDo not share features with normal dependencies
Dev dependenciesDo not turn on features unless building a target that needs them

The cost is that a crate may be built more than once with different features, which raises build time. The reference points to the duplicates view of cargo tree for finding these.

Why it matters for security

Every enabled feature is more compiled code, and sometimes more dependencies. A network or compression feature you never use still brings parsers, and parsers are where many memory safety and denial of service bugs live. Fewer enabled features means less code to be affected by an advisory.

But do not overclaim. Whether a feature removes the vulnerable code depends on that advisory. Read which feature gates the affected function.

Steps to trim safely

  1. List what is enabled and why:
cargo tree -e features -i dependency_name
  1. Find the chain that enabled the feature you do not need.
  2. If your own manifest caused it, disable defaults and list only the features you use.
  3. If a parent caused it, open an issue upstream or accept it with a note.
  4. Build, test, and re-run the tree to confirm the feature is gone.
  5. Record the result so a later edit does not undo it.

A caution on testing

Features are additive, so a crate must work with any combination. If you remove a default feature and something breaks, that usually means your code relied on it implicitly. Add it explicitly rather than turning defaults back on.

Try it yourself

Click through it at your own pace, or open it full screen. Look at how knowing which code is used changes what you fix first.

Quick check

Does a build dependency share features with my runtime dependency?

With resolver 2 it does not. Older resolver behavior unified them.

Is disabling defaults enough to mark an advisory not affected?

No. Confirm the affected code is gated by a feature that is truly off in your build.

Safeguard reachability analysis can help separate affected code from code you never call, and a free scan is available at gold.safeguard.sh/scan.

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.