¹ https://rust-lang.github.io/goals/2024h2/sandboxed-build-scr...
¹ https://rust-lang.github.io/goals/2024h2/sandboxed-build-scr...
It would be a big pain for many that are in the unfortunate position to really need build scripts, though.
There are still elephants (or rather mammoths) in the room for supply chain security, such as having 1500 nested deps for a standard project. It’s like we never woke up from the nightmare of leftpad.
If your project had code from 100s of individuals, new versions can be pushed instantly, and nobody wants to review the code, then you have a time bomb. And also other problems.
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.
It doesn't really matter anyway, because nobody is reading anything in their dependencies before it gets downloaded. Malware can also be hiding in plain sight in source code, as this attack and many others shows.
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.
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.
Id like to add project provided runtime capabilities/permissions (eg. apparmor profiles) to the list to.
Maybe the day will come, where projects not providing these things will be considered broken, like nix does.
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.
If you have a serious proposal, then I encourage someone to seriously propose it. Cargo is an understaffed open source project that, like the rest of the Rust project, relies largely on volunteers. However, gesturing to unspecified internal weird mechanisms does not strike me as a serious proposal worthy of consideration by anyone, so I'd suggest working on that first.
> The sandbox should not have network access, but cargo needs network access to download the package in the first place.
Naturally. Use `cargo fetch` to download a package locally without invoking any build step: https://doc.rust-lang.org/cargo/commands/cargo-fetch.html
This is the kind of decision users likely don’t understand without looking at the source code of a crate and it’s bad UX to push it to be their responsibility.
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.
Functions should only have access to their arguments. Nothing more. We need to end ambient authority.
It guarantees that pure functions are pure.
https://www.microsoft.com/en-us/research/publication/safe-ha...
https://downloads.haskell.org/ghc/latest/docs/users_guide/ex...
Yes, I want this but in a fast, compiled systems language like rust.
Rust certainly borrows from Haskell. Like all good languages. But I’m not aware of Haskell beating rust in program performance & memory usage benchmarks.
SeL4 was first written in Haskell and proven correct in Haskell. Then, with a great many years of effort, ported to C and proven correct there. If Haskell were a viable systems language, I suspect the kernel would not have been converted to C.
> Like lazy evaluation and memoisation
Yes, that causes performance impact. If you don't want the performance impact then don't write code that uses those behaviors. Sure, that rules out large parts of the ecosystem, but I said Haskell was a systems language not that its ecosystem was generally suitable for systems programming.
> however Haskell manages memory
No, Haskell's memory manager is world class, with two (at least) tunable garbage collectors.
> But I’m not aware of Haskell beating rust in program performance & memory usage benchmarks
Nor am I!
> If Haskell were a viable systems language, I suspect the kernel would not have been converted to C.
I suspect they converted it to C because you can't write a kernel in a managed language with a garbage collector.
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.
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.
> Asking the user to not make mistakes is the c++ approach to security
Then demand crates.io do better by actually curating every version of every published crate.
(Oh and btw, proc macros also run arbitrary code.)
(It mostly boils down to "somebody needs to do it". I'd really like proc macros precompiled to wasm by crates.io…)
wasm has the additional benefits of allowing something like pre-compiling binaries once on a central server and thus skipping the CPU cycles for compiling all the macro crate dependencies on every crate compile. So even the people who don't care much about the security benefits have a reason. I'm kind of the "don't care about security" side because (as said elsewhere) it's trivial (https://docs.rs/ctor/latest/ctor/) for any macro to insert code that will run when compiled binaries/tests are run. You need the entire thing in a sandbox anyway, not just the macros, and that's something that can't be provided by cargo by default.