Skip to content

Fix a bug involving optional non-dev dependencies#111

Merged
Shnatsel merged 2 commits intorust-secure-code:masterfrom
smoelius:master
Jan 22, 2026
Merged

Fix a bug involving optional non-dev dependencies#111
Shnatsel merged 2 commits intorust-secure-code:masterfrom
smoelius:master

Conversation

@smoelius
Copy link
Collaborator

This PR fixes a bug concerning optional non-dev dependencies.

The bug: cargo supply-chain json --no-dev suggested a project of mine was no longer relying on libz-rs-sys: https://github.com/trailofbits/cargo-unmaintained/actions/runs/21091621244/job/60663642551#step:8:98

The reason was a difference in gix-features 0.44.1 and 0.45.2. The former lists libz-rs-sys as an optional dependency; the latter does not list libz-rs-sys at all.

Furthermore, to determine a project's dependencies, extract_non_dev_dependencies was considering only the project's declared dependencies. What the project actually used was irrelevant. Thus, merely listing libz-rs-sys as an optional dependency of gix-features 0.44.1 was enough to include it in my project's supply chain.

The fix: extract_non_dev_dependencies no longer determines dependencies using a project's declared dependencies. Now, extract_non_dev_dependencies uses resolve.nodes to determine the dependencies the project actually uses.

This approach makes --no-dev slightly slower, but it produces more accurate results.

If I run the fixed version on the project where I observed the bug, I no longer see libz-rs-sys, and several other dependencies are eliminated as well.

Full disclosure: I used an LLM (Claude) to diagnose the bug, to write the fix, and to prepare the test.

@Shnatsel
Copy link
Member

That sounds reasonable, but I'm not thrilled about including over 4,000 lines of test data, since it's going to get really difficult to diagnose the issue if it ever reoccurs. Could you minify it? If the issue is as you describe, then simply depending on any crate with optional dependencies should suffice.

@smoelius
Copy link
Collaborator Author

I should have explained how the test works. Let me please do that now.

The deps_tests/flate2_1.1.5.metadata.json file is based on the output of these commands:

cd ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/flate2-1.1.5
cargo metadata | jq . | sed "s,$HOME,\$HOME,"

However, the optional dependency libz-rs-sys is synthetically added. Here is the diff:

diff
+    },
+    {
+      "name": "libz-rs-sys",
+      "version": "0.5.0",
+      "id": "registry+https://github.com/rust-lang/crates.io-index#libz-rs-sys@0.5.0",
+      "license": "MIT",
+      "license_file": null,
+      "description": "A drop-in replacement for libz-sys using zlib-rs",
+      "source": "registry+https://github.com/rust-lang/crates.io-index",
+      "dependencies": [],
+      "targets": [],
+      "features": {},
+      "manifest_path": "$HOME/.cargo/registry/src/index.crates.io/libz-rs-sys-0.5.0/Cargo.toml",
+      "metadata": null,
+      "publish": null,
+      "authors": [],
+      "categories": [],
+      "keywords": [],
+      "readme": null,
+      "repository": null,
+      "homepage": null,
+      "documentation": null,
+      "edition": "2021",
+      "links": null,
+      "default_run": null,
+      "rust_version": null

The other two json files exist because the deps test requires them.

But to your point:

Could you minify it? If the issue is as you describe, then simply depending on any crate with optional dependencies should suffice.

You would prefer a fixture, e.g., a small package that enables an optional feature on a dependency?

@Shnatsel
Copy link
Member

You would prefer a fixture, e.g., a small package that enables an optional feature on a dependency?

Yes, either that or cargo-metadata output derived from such a minimal fixture.

I've gone the fixture route in https://github.com/rust-secure-code/cargo-auditable/tree/master/cargo-auditable/tests/fixtures but I think committing the JSONs produced by cargo metadata is probably also fine.

@smoelius smoelius force-pushed the master branch 2 times, most recently from ff9aea3 to 316352e Compare January 21, 2026 00:06
@smoelius
Copy link
Collaborator Author

I think this does it. I broke the changes into two commits. The first commit adds a fixture and a test (that fails). The second commit implements the fix.

Note that, in the fixture, libz-rs-sys is an optional normal dependency, but a non-optional dev dependency.

@Shnatsel
Copy link
Member

Looks good. Thanks!

@Shnatsel Shnatsel merged commit 84af219 into rust-secure-code:master Jan 22, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants