I think we may need to enter a world where there are fewer, heavily audited, libraries and dependency depth is limited. Allowing unvetted dependencies to be installed by default is not a good way forward. App stores have a similar problem and I think a lot of lessons have been learned there that can be applied.
Here is my learning building PMG:
Sandboxing is good when the workload is predictable, and the goal of sandbox is to guard against exploitation of vulnerabilities, like sandbox protecting chrome tabs (renderers). But unfortunately build scripts are not predictable, at least not in npm/pypi world and I have seen build scripts doing weirdest of the things which is no different from malware. When popular packages do weird things, build breaks and users end up turning off the sandbox. This is a perpetual problem to deal with while building sandbox (or any least privilege solution) to protect unbounded workloads.
It isn't so much a question of sandboxing build.rs, as fundamentally changing the way that foreign dependencies are integrated into the rust toolchain (i.e. moving from a rust-centric system like Cargo to something more general like buck2)
To solve the problem of native/C dependencies, they just bundle pre-compiled libraries as data files.
Rust could do the same thing.
Any C library that's also packaged by debian supports being built under these conditions because it's required for everything except non-free packages: https://www.debian.org/doc/debian-policy/ch-source.html#main...
As the link you posted mentions, you need a tiny bit more than that: you also need write access to the temporary directory (/tmp and similar). Many build tools temporarily store files there; for instance, unless things have changed since I last looked, if you don't use the -pipe argument the C compiler stores its temporary intermediate files (preprocessor output, assembler input) there.
Which is the result of how bad dependency managment is outside (i.e. DLL-hell).
Pretty much all other use cases of build.rs can be sandboxed. Well, there is sqlx that wants to connect to database at expansion time to compile check-queries (yew).
Although I suppose that's still doing a lot of shenanigans at compile time. It could be sandboxed pretty well (theoretically). I'd hate to give it up completely though, getting a compile time error when SELECT query params or return values have type mismatches is extremely nice.
I would argue that, if a build script doesn’t work in the setting, then it doesn’t deserve to be installable by a default cargo command.
This seems like an excuse, not an actual objection.
Linux can do seccomp or Landlock or gVisor or a combination. Seccomp and gVisor need no privileges. Windows has its internal weird mechanisms. Mac has sandbox-exec.
Cargo could easily pick an appropriate sandbox for each major platform and ship it by default.
> If you only care about Unix, then you can do this yourself today by building code in your sandbox of choice.
This is ridiculous. The sandbox should not have network access, but cargo needs network access to download the package in the first place.
It would be a big pain for many that are in the unfortunate position to really need build scripts, though.
Cargo, please PLEASE give me a way to disable third-party build.rs and whitelist the ones I need. And please loudly mark any update that adds a build.rs where there was none before.
See https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.h...
Audit and limit crates (cargo-deny &| cargo-crev, && --offline) until tools exist to audit build.rs safety semi-automatically ($$ safeguard.sh maybe).
The root problem is two parts:
1. crates.io doesn't do mandatory curation. Lack of curation is fail. It's time-consuming and costly for reviewers without a doubt, but so is letting an ecosystem gain maximum entropy (go to shit) by Tragedy of the Commons depending entirely on the honor system. Name squatting, low-quality, unmaintained, typosquatting, and malware are the consequences of too much self-service / semi-self-service freedom.
2. Many, many cargo subcommands are over-eager to run build.rs because it assumes trusted crates:
In an untrusted/uncurated crates world and a build.rs exists or exists in a selected dependency, it shouldn't run at cargo-add time (unless it must). If it exists, on first run, it should be presented to the user in a viewer for manual review unless a magic CLI flag/env var is specified to accept it.
These 2 factors combined appear to create a Swiss cheese holes failure mode for running arbitrary crate `cargo add`. I have confidence a suitable add-in workflow &| standard command &| repository workflow will be adjusted to reduce the attack surface of the ecosystem.
The vast majority of crates don't need build scripts, so it is vaguely feasible to audit the list of crates you use that might need them.
(Oh and btw, proc macros also run arbitrary code.)