Live data from Hacker News

Malicious Rust crate Arrayref runs a build-time payload

safedep.io

271–280 of 529 posts

Re: Malicious Rust crate Arrayref runs a build-time payload

#271
post #186

Earlier quoted context omitted.

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.

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.

Cargo is a cross-platform tool, so when it ships a sandboxing solution it will need to be a cross-platform solution, and because this is a security feature it needs to be bulletproof, so no half-measures like Docker. Something like a WASM runtime might fit the bill, though that will be much easier to get working for typical proc macros than for typical build scripts. If you only care about Unix, then you can do this yourself today by building code in your sandbox of choice.

Re: Malicious Rust crate Arrayref runs a build-time payload

#273

Earlier quoted context omitted.

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

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

Rust, like C, C++, and every other systems programming language, is all about giving users the power to make mistakes. The philosophical difference when it comes to Rust is simply that it tries to force the user to flip off the safety on the gun before letting you shoot yourself in the foot. A Cargo config option letting people opt-out of sandboxing would be fully in line with Rust's philosophy.

Re: Malicious Rust crate Arrayref runs a build-time payload

#274
post #206
post #155

Earlier quoted context omitted.

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.

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

> Just denying write access outside the build directory and denying network access

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.

Re: Malicious Rust crate Arrayref runs a build-time payload

#275
post #46

Earlier quoted context omitted.

Compromising the code that is then most likely run in a test instead of compromising a build script is just a very slight inconvenience for the attacker. I share the dislike for arbitrary build scripts but restricting them will not help the supply chain issue in a significant way. Also there are several ways to control build.rs execution in the Cargo ecosystem as well, for example with cargo-deny.

The problem is that build scripts run automatically without user consent or intevention. `cargo add` is sufficient to compromise you, before you have a chance to even vet the code.

`cargo add` just modifies your Cargo.toml, it doesn't build anything.

Re: Malicious Rust crate Arrayref runs a build-time payload

#276
post #214

Earlier quoted context omitted.

build.rs changes nothing about how easy it is to integrate with C. What does simplify: figuring out how to supply library you need at build time. 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).

sqlx at least has the (optional) offline mode, where you "cargo sqlx prepare" once (which wants access to a db) and then you can build in offline mode which typechecks your queries against local files. 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 pa…

sqlx offline mode being opt-in instead of default is what bothers me. You know what else can validate that your queries return what you expect? Integration tests. Shoutout to sqlx for #[sqlx::test] though.

Re: Malicious Rust crate Arrayref runs a build-time payload

#278

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

How many times do we need to learn that sandboxing won't magically save us.

Re: Malicious Rust crate Arrayref runs a build-time payload

#279
post #276

Earlier quoted context omitted.

sqlx at least has the (optional) offline mode, where you "cargo sqlx prepare" once (which wants access to a db) and then you can build in offline mode which typechecks your queries against local files. 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 pa…

sqlx offline mode being opt-in instead of default is what bothers me. You know what else can validate that your queries return what you expect? Integration tests. Shoutout to sqlx for #[sqlx::test] though.

I also wish that it would be the default. Integration tests are fine, but they aren't compile time. Elevating them to compile time and using an LSP enabled editor makes it just underline SQL errors before I've even had a chance to run a manual compile let alone a test...

Re: Malicious Rust crate Arrayref runs a build-time payload

#280

Earlier quoted context omitted.

This is spot on. I am extremely uncomfortable with the large number of transitive dependencies that end up in pretty much any non-trivial rust application. No amount of memory safety will save us if a tiny, ubiquitous library that nobody scrutinizes because it’s nested eight layers down the dependency graph gets compromised. I think Go apps tend to have better dependency hygiene because the language has a better stan…

I think Go ends up with fewer dependencies mostly because there is more friction in finding them. With rust (and npm) you just "cargo search xxx", then "cargo add xxx". Go makes you web search and poke around github looking for something. It's not onerous or anything, but just that extra step slows things down just a bit. C projects tend to have the least because it's even more annoying to add them and you have to cr…

Actually I think this is more of a culture thing. Or maybe "is also" a culture thing.

One of the core tenets of early Go was the maxim "a little copying is better than a little dependency".

Probably because of this stance, they didn't even HAVE a dependency-management solution for years

I strongly agree the fewer dependencies the better, on average.

Post reply on HN