Filtering against `cargo tree` under-includes dependencies, does not accurately reflect feature unification in a workspace
Uncommenting this line in #210 causes the test to fail:
https://github.com/rust-secure-code/cargo-auditable/blob/6c39a181300a31553bebb55b26441fe7cad0a223/cargo-auditable/tests/it.rs#L593
This is using the fixture runtime_and_dev_dep_with_different_features which tests for over-zealous feature unification. If a package is used both as a dev-dependency and as a normal dependency, the features enabled on it when it is used as a dev-dependency do not impact the features enabled on it in the runtime dependency tree.
cargo metadata performs the erroneous over-zealous feature unification, which is why we have to filter it against the output of cargo tree --edges=normal,build to get rid of the extraneous dependencies.
It seems that either the SBOM emitted by Cargo or our handling of it reintroduce the problem.
cc @tofay
It seems to be a bug in the upstream SBOM support. The optional_transitive_dep crate should not be present in the SBOM emitted by Cargo, but it is: top_level_crate.cargo-sbom.json
The cargo SBOM is correct for that test fixture if you build with -p top_level_crate. If you don't, then cargo passes all the workspace members over to the feature resolver, causing optional_transitive_dep to be activated. ~~But yeah, it's a cargo bug.~~
Hmm... I don't think this is a cargo-auditable or cargo SBOM bug. Perhaps it's a cargo bug relating to workspace feature resolution but it's not a reporting bug.
I think the cargo tree approach is bugged as it will not report the dependencies that we don't think cargo should be compiling but that cargo is actually compiling.
Consider https://github.com/rust-secure-code/cargo-auditable/commit/036acd1f217edce94274c0c3a1aabea7d6572d07. When you run the example with cargo run -p top_level_crate and cargo run you get different results. The cargo SBOM accurately includes optional_transitive_dep in both cases.
Consider https://github.com/rust-secure-code/cargo-auditable/commit/036acd1f217edce94274c0c3a1aabea7d6572d07. When you run the example with
cargo run -p top_level_crateandcargo runyou get different results.
Well that's interesting (and horrifying). Thanks for pointing it out.
The cargo SBOM accurately includes
optional_transitive_depin both cases.
To clarify, it doesn't include it in all cases. Rather, it includes optional_transitive_dep when executing cargo run workspace root, but excludes it when running cargo run -p top_level_crate in the workspace root or when doing cd top_level_crate && cargo run. This behavior matches the cargo run output and appears to be correct.
I've updated the title of the issue and I'm going to take a long, hard look at my usage of cargo tree to try and accurately reflect this interesting behavior of Cargo.