Remix.run Logo
jakubadamw 3 hours ago

Cargo desperately needs sandboxing for build.rs scripts. It’s been attempted before, but didn’t go very far¹.

¹ https://rust-lang.github.io/goals/2024h2/sandboxed-build-scr...

abhisek 2 hours ago | parent | next [-]

This is exactly what PMG is designed for ie. install/build time process level sandboxing. It currently doesn't support cargo, but I believe the challenges are same.

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.

https://github.com/safedep/pmg

Asraelite an hour ago | parent [-]

The "How PMG Works" section on Github does not actually explain how it works

swiftcoder 2 hours ago | parent | prev | next [-]

build.rs by design can run absolutely anything. There tons of build.rs scripts that invoke a whole-ass C compiler toolchain to build and link C dependencies...

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)

kibwen an hour ago | parent [-]

The vast and overwhelming majority of build scripts are building C code, so the other solution is to move away from integrating with C dependencies to native Rust dependencies, in which case adding friction to build scripts would be less noticeable.

robhlt 2 minutes ago | parent | next [-]

Just denying write access outside the build directory and denying network access would go a long way and won't break pretty much any well-behaved build systems.

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...

thayne 39 minutes ago | parent | prev [-]

One of rust's strengths is it's ability to interface relatively easily with existing c code without having to rewrite absolutely everything in rust. I don't think that is something we want to give up.

Panzerschrek 2 hours ago | parent | prev | next [-]

Sandboxing for build scripts can't work properly. If you sandbox too much, some necessary stuff can't be done. If you sandbox too little, it has no practical value.

amluto an hour ago | parent | next [-]

As an easy start, how about letting build scripts read /usr, read and write a temporary build directory, have some /tmp scratch space, and be allowed to write its final output artifact. No network and otherwise isolated from the rest of the system.

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.

lobofta 2 hours ago | parent | prev [-]

So let each build script define its own level of sandboxing and then users can determine whether they are okay with that level or not, e.g. `cargo build --sandbox-level=...`

jurgenburgen an hour ago | parent [-]

That’s not solving the problem, that’s avoiding it by making it the users fault if they make a mistake.

weinzierl 2 hours ago | parent | prev | next [-]

Sandboxing just build.rs would only be be a minor inconvenience for the attacker, nothing more. The attacker can always as easily compromise the binary you build and as soon as you run it (e.g. in a test) you are owned.

It would be a big pain for many that are in the unfortunate position to really need build scripts, though.

Aurornis 2 hours ago | parent | next [-]

I imagine it would be sandboxed by default with an escape hatch to run build scripts outside of the sandbox with user verification. It makes people stop and think about what’s happening. Not perfect, but it does help. When working on JS ecosystem projects I manually approve build scripts and spend some time researching dependencies with build scripts to see if I can avoid running the build script. Some people will ignore it and run everything, but it’s a huge step in the right direction to make it operator-decided.

insanitybit 2 hours ago | parent | prev | next [-]

It would be more than a minor inconvenience. I can handle sandboxing my tests and production infra, but I can't handle sandboxing build scripts because I don't own that code in any sense.

kibwen an hour ago | parent | prev [-]

At the very least, it wouldn't be overly onerous when adding a dependency that requires a build script to require an opt-in via Cargo.toml, e.g. `build-script = true`. You'd make it viral so that any transitive dependency that requires a build script would affect its parent, then add the key as defaulting to `true` so as to not break backwards-compatibility, then switch the default to be more restrictive over a new edition. (This same key could be used to prevent proc-macros from having arbitrary system access as well, where by default proc macros could be compiled to WASM and run in a WASM sandbox and treated as pure functions.)

somat 2 hours ago | parent | prev | next [-]

I mean sure, but anything the build script could do, the build artifact could also do, That is to say, if you don't trust your source why do you trust the thing it compiles into?

burnt-resistor 2 hours ago | parent | prev | next [-]

Never going to work. Crates must be audited for behavior before use.

Aeolos 2 hours ago | parent [-]

cargo add + rust-analyzer instantly executes build.rs before you have a chance to audit the code.

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.

praseodym an hour ago | parent [-]

cargo-deny can audit build scripts, but unfortunately not prevent execution of malicious build scripts exactly for the reason you gave. It could still help if you only ever use cargo add and update in a sandbox.

See https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.h...

krautsauer 2 hours ago | parent | prev [-]

https://news.ycombinator.com/item?id=49374811

(Oh and btw, proc macros also run arbitrary code.)

quotemstr 2 hours ago | parent [-]

There's no good reason a proc macro can't run in a no-IO sandbox by default. None. Doesn't require a language change. Doesn't require some microvmcapabilityeffect BS. It requires looking people straight in the eye and saying "no" when they complain about needing to prompt for privileges.