-
Notifications
You must be signed in to change notification settings - Fork 71
Build-time execution sandboxing #475
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
Comments
This issue is not meant to be used for technical discussion. There is a Zulip stream for that. Use this issue to leave procedural comments, such as volunteering to review, indicating that you second the proposal (or third, etc), or raising a concern that you would like to be addressed. cc @rust-lang/compiler @rust-lang/compiler-contributors |
related, from a wasm running builds perspective: |
@rustbot second |
@rustbot label -final-comment-period +major-change-accepted |
Should the two unchecked checkboxes under "Process" be checked now? |
Sure -- I've ticked off those boxes. |
Note: Inline revisions after initial proposal are denoted by square brackets. Addendums are entire sections added after initial proposal.
Proposal
This cross-team major change proposal intends to add support for sandboxed build scripts and proc macros (referred to as build-time execution from here on out) by achieving the following:
The current idea is to introduce a minimum API that can cover a majority of build scripts of which usage must be explicitly declared (such as in the Cargo.toml). Any API not declared but used would result in a compilation error.
To ensure that sandboxing is a first-class feature, we also need to achieve two things: ensure the isolating runtime is ubiquitous and ensure that options are easily configured by the user. The former is possible with rustup, and requires little to no effort on their end as it should just be a new component. The latter will require changes from Cargo and the Rust compiler itself.
[ Unless better alternatives arise, the intended sandboxing implementation is a WebAssembly-based runtime. Wasmtime seems to be the best solution, followed by a stand-alone wasm runtime with Wasi. Using a WebAssembly-based runtime allows us to leverage existing sandboxing efforts in the browser space, which saves us a lot of work and likely provides better sandboxing than any hand-rolled attempt. ]
Finally, introduction of this feature should be gradual. We should introduce it as opt-in, and re-evaluate defaults at the next Rust edition. This allows us to introduce it as a feature of a minor Rust version rather than needing to wait until the next Rust edition.
For an opinionated overview of why I think this feature is worthwhile:
These four objectives require support from a variety of teams so I’d like to get approval in some way from at least (but not limited to) the following teams and working groups:
Once approved, the plan is to gather feedback, draft up and push for necessary RFCs, and implement required features. Landing an isolating runtime should be the first priority, as we can then build off the API and compiler features from there. If a working group is necessary, then I can look into that as well. (I may need guidance on this!)
I believe this is the right time for Rust as a language to consider and work towards this. I believe the ecosystem is mature enough for us to have meaningful insight on how build-time execution is used while still being flexible enough for large new changes such as this.
Addendum A: C dependencies
Thanks @bjorn3 for this feedback!
A huge customer of build scripts are crates that have a direct reference to C libraries. This is a problematic section that is difficult to isolate without heavy consideration. Non-standard locations, access to large amounts of locations, and other C-isms make it difficult to do so without tedious work for the end-user. Bringing in a stand-alone C compiler (as seen with Zig) also has it's own set of challenges that seem unresolved at this point in time.
As a result, this MCP is not intended to support C dependencies and only targets pure-Rust dependencies. However, I do believe work done should always keep C dependencies in mind, and leave support for C dependencies for the future.
Addendum B: Threat Model
Thanks to @wesleywiser and @The 8472 for this feedback!
Note that while I primarily want to push for it as a security feature, I want to emphasize that there are benefits beyond security. As a result, even if this is a relatively niche situation, there are still benefits beyond security that should be considered as well. This is not intended to be a universal solution to build-time threats. In fact, this by itself can easily be bypassed, and that is fully acceptable.
We're specifically targeting malicious dependencies that try to exfiltrate data at build-time, via a malicious proc-macro or build script. We assume that the prod environment is sufficiently secured such that malicious actors aren't able to do anything if they get malicious code running (e.g. there's network mitigations in place).
We can't strictly apply the same security measures on our prod hosts as we do with our CI as there's necessary holes we need to make in our security for CI to be functional (network access, for example, to fetch resources). As a result, we need a mitigation lower in the stack to help with this; this is that mitigation.
This is a very weak layer of defense, and there are other ways for malware to bypass this, but the goal here is to block the lowest hanging fruit. Forcing malicious actors to defer to runtime or to tests (which a can be a good security followup), where other mitigations should be in place, is the entire goal. We can build upon this layer of defense later; but for now something is better than nothing, in my opinion. Plus, I believe that without this mitigation in place, other potentially stronger defenses may be rendered moot.
A notable follow-up on this would be test isolation: Most proper unit tests only need a temp file or directory at best, if they need any disk access at all. Networked unit tests also seem like an incredible exception; as a result, once this gets implemented, work to improve that area may be a natural extension.
Addendum C: Maintainence & Security Response
Thanks to @Florian Weimer, @Quy Nguyen, and @The 8472 for this feedback!
Sandboxing build-time execution also subtly changes the expectations that people have. Notably, as sandboxing becomes a proper Rust feature, so does any vulnerabilities. In other words, this feature would extend the surface of vulnerabilities that Rust needs to maintain and protect against as people will certainly assume that sandboxing will be secure. A poor implementation could be catastrophic for our users. As a result, even if Rust doesn't advertise this as a security feature, we will likely need to treat (at least some) bugs as security vulnerabilities to Rust themselves. This also means we need a faster response to these issues, which is a non-trivial maintenance cost over other new features.
As someone effectively external to the inner workings of Rust, I won't make any assumptions on how difficult it is to maintain such a feature. That being said, I do have faith in Rust's stabilization practices, so I believe what will likely happen is that this feature will have an extended stay as a nightly feature until we have significant confidence that there won't be security issues at launch (perhaps the Secure Code Working group could help with this). We could also require security oriented reviews of any sandboxing changes (to what extent is to be determined later). This can hopefully mitigate any huge issues after this feature is stable. Plus. the opt-in nature of this could allow us to gain additional feedback before maintaining a more aggressive stance on sandboxing, if we decide to do one.
I also see this feature as a foundational one for many other previously mentioned potential features. The initial cost of maintaining this feature as-is might be significant, but as more and more features are built upon it, I imagine the cost to maintenance becomes shared with dependent features. Therefore if maintainability is a concern, I believe considering it as an investment for future (much more valuable) wins is reasonable.
Addendum D: Scope
This is an authoritative list of what explicitly is not in scope of this MCP:
Mentors or Reviewers
None yet
Process
The main points of the Major Change Process are as follows:
@rustbot second
.-C flag
, then full team check-off is required.@rfcbot fcp merge
on either the MCP or the PR.You can read more about Major Change Proposals on forge.
Comments
test
environment as potential future security-oriented work post-build-time execution sandboxing.This issue is not meant to be used for technical discussion. There is a Zulip stream for that. Use this issue to leave procedural comments, such as volunteering to review, indicating that you second the proposal (or third, etc), or raising a concern that you would like to be addressed.
The text was updated successfully, but these errors were encountered: