Separating fetching from building for better security
Nemo157:
grothesque:
For example, truly replicating the fetches that some
cargo buildinvocation would perform without runningcargo buildseems very difficult currently.Hmmm, this seems odd to me, I've been using a similar wrapper script for years doing a simple
cargo fetchand not run into such issues.
A simple cargo fetch often works, but I am not aware of a way to limit it to a particular set of Cargo features. In particular, I believe that there is no way to make it aware of the features needed for a particular cargo build. So it tends to fetch too much, which may or may not be a problem.
But cargo fetch can also fail to fetch enough for a particular cargo build. For example, suppose a crate has a direct dependency named foo, and foo has
[features]
tls = ["dep:rustls"]
[dependencies]
rustls = { version = "...", optional = true }
A user can run
cargo build --features foo/tls
which activates a feature of the direct dependency. But cargo fetch has no corresponding --features option, so a wrapper using cargo fetch alone cannot say “fetch exactly as that build would fetch”. If rustls is not already cached, the later --frozen build can fail.
Even if one disregards such cases and if one does not worry about fetching more than necessary, making a wrapper cover most of Cargo’s command line interface (e.g. +nightly, --config, -C, etc.) is quite complicated.
In the two-phase fetch-then-build-workflow, --frozen is already close to the second phase: run the requested command without allowing network access or lockfile changes. The missing first phase is a way to ask Cargo to perform exactly the fetching that the command would need, then stop.
In this way --fetch-only would be a natural addition to the existing --locked, --offline, and --frozen options of Cargo. It would make it easy for wrappers like yours or mine to separate fetching from building cleanly and robustly.
Discussion in the ATmosphere