Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sandbox/jail build scripts #5720

Open
ishitatsuyuki opened this issue Jul 12, 2018 · 11 comments
Open

Sandbox/jail build scripts #5720

ishitatsuyuki opened this issue Jul 12, 2018 · 11 comments
Labels
A-build-scripts Area: build.rs scripts C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` S-needs-rfc Status: Needs an RFC to make progress.

Comments

@ishitatsuyuki
Copy link
Contributor

Build scripts has too much capabilities than it would actually need. As a security measure, it may be good to perform some kind of sandboxing for them.

Things we could be restricting:

  • Act as the nobody user, disallowing read of private files, or deletion of important files.
  • Disable networking (with some way to opt out).

Strategy we could take:

  • Just use some existing mechanism (changing user) to downgrade privileges. Is this possible?
  • LD_PRELOAD and hook libc, which is what Gentoo use. Possible to bypass. Availability on Windows: possible, but probably harder than Linux.
  • Full sandboxing with gVisor. Safe, but doesn't work for Windows indeed.
@alexcrichton alexcrichton added the C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` label Jul 12, 2018
@joshtriplett
Copy link
Member

Unfortunately, dropping privileges tends to require starting as root.

However, things like seccomp might help, though they're Linux-only.

@crepererum
Copy link

Depends. On Linux, you could use user namespaces (if they are enabled for that kernel) or helper tools like bubblewrap. Bazel also implements sandboxing (see this older blog post as well as this one). Firefox also implements different mechanisms on different systems to isolate certain processes. I think, this should be implemented by some sort of general purpose crate that then has OS-specific solutions. Worst case is that no sandboxing is implemented on your system (in which case cargo could print a warning.

@ehuss ehuss added the A-build-scripts Area: build.rs scripts label Dec 30, 2019
@sam-ka
Copy link

sam-ka commented May 25, 2021

We could take the setuid-helper approach here, where we ship a small binary that sandboxes the main cargo binary. I believe this is what Google does to sandbox Chrome and Electron on Linux.

@epage
Copy link
Contributor

epage commented Sep 18, 2023

See also rust-lang/compiler-team#475

My ideal:

  1. Allow opt-in full sandboxing of proc macros via wasm
  2. Extend the system with capabilities requested via Cargo.toml for access to different system resources
  3. Extend the system to build.rs

I see proc macros as the MVP for this because most can be "pure" (no external state or side effects) while build.rs inherently interacts with external state and has side effects.

@gdennie
Copy link

gdennie commented Nov 25, 2023

One possible way to control the scope of scripts is to require that their system access go through compiler provided precompiled libraries. These libraries may then respect configuration files and so forth to allow, deny, and log their effects. Additionally, these libraries can provide a great API into the build process itself while also making scripts both more powerful and quick to compile.

@CinchBlue
Copy link

My discussion for #13113 was redirected here. I just read rust-lang/compiler-team#475. It sounds like the WASI team is going for a file/directory-based directories interface...

  1. Extend the system with capabilities requested via Cargo.toml for access to different system resources

...so it sounds like adding a [resources] section similar to [dependencies] for non-.rs source file resources would be useful for providing this "allowed" list.

@epage
Copy link
Contributor

epage commented Jan 15, 2024

Just noticed rust-lang/rfcs#2794 which might be relevant

@epage
Copy link
Contributor

epage commented Jan 15, 2024

Also looking to compile prior art for permissions / capabilities

@epage
Copy link
Contributor

epage commented Sep 26, 2024

The more I think about this, I worry whether sandboxing will be the right approach. It is the most complete but that will also add its own burdens, including build time as users won't be able to reuse builds between the host (build scripts) and target (runtime).

I find cackle's approach of ACLs interesting. If we had a linter that could trace your theoretical call stacks, then you could get a report of all unsafe and FFI calls. You can then build up abstractions for these a priori or ad-hoc (fs read, fs write, env read, spawning), -sys link name, crate name, etc) and approve them either in your own code or in your dependencies.

This would allow you to more easily audit any non-pure operation in your dependency tree that you would actually call.

Compared to sandboxing, the main downside is we can't enforce how APIs are called, like what paths are read or written.

@weihanglo
Copy link
Member

weihanglo commented Sep 26, 2024

including build time as users won't be able to reuse builds between the host (build scripts) and target (runtime).

This is exactly what I noticed during the experiment rust-lang/rust-project-goals#108 (comment)! I found it pretty frustrating 😞.

Compared to sandboxing, the main downside is we can't enforce how APIs are called, like what paths are read or written.

It is indeed promising. And agree that guarding API calls at the per-crate level somehow hurts the usability of build scripts because it doesn't consider the purpose of an API call. Here are some tricky situations: controlling calls into a seemingly safe executable but with malicious arguments, or calling $CARGO metadata, where we may need to handle changes in the registry cache and rustup toolchain overrides.

Just a wild idea. We could probably provide an interactive approval session, allowing the user to run the build script first and pre-approve all API/syscall calls. Then, we could export the pre-approval list to a file for Cargo to read.

Anyhow, it comes down to what level of configurability we'd like to provide.

@epage
Copy link
Contributor

epage commented Sep 26, 2024

Just a wild idea. We could probably provide an interactive approval session, allowing the user to run the build script first and pre-approve all API/syscall calls. Then, we could export the pre-approval list to a file for Cargo to read.

While this would be approval-after-the-fact, this isn't far from cargo fix support for this being a lint.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-build-scripts Area: build.rs scripts C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` S-needs-rfc Status: Needs an RFC to make progress.
Projects
None yet
Development

No branches or pull requests

10 participants