rune-rs / rune

An embeddable dynamic programming language for Rust.
https://rune-rs.github.io
Apache License 2.0
1.7k stars 86 forks source link

Can rune run untrusted code/is it sandboxed? #569

Open boehs opened 1 year ago

boehs commented 1 year ago

I couldn't find any issues about this, and it's not clear from the docs. Can I run untrusted rune scripts in a larger rust project?

Take

But it's still tricky enough that streamers who have limited programming experience struggle getting up and running. I wanted them to be able to write their own commands. Ones they could just drop into a folder and presto - you're up and running.

Could I make a bot that I host on my own server and let streamers write commands for their own streams that I run on that server in a secure way?

udoprog commented 1 year ago

Everything except memory usage in Rune can be sandboxed right now. To restrict memory use we either need rust-lang/rust#32838 to land or switch to using data structures in the runtime which we can plug a custom (fallible) allocator into. Without this, if someone installs a rune script which uses a lot of memory (think building a large array) that uses relatively few instructions it would eventually cause a panic when memory runs out which could easily DOS your server.

For the rest, what you want to do to create a sandboxed environment (rune-wasm is a good example). Where you only install the builtin modules without io. None of the builtin modules except io interact with the environment, and for io it's just to provide printing for which you should build your own mechanism (rune-wasm captures all output) if you want println! and the like to work. Then you add whatever you need on top of it. Everything you add, you're obviously responsible for maintaining the integrity of the sandbox.

Scripts should also be budgetted which causes the virtual machine to error in case it executes more instructions than the budget permits. This allows you to control how much execution time to give each run.

How to deal with memory usage?

To get back to the allocation issue, In principle you could build an environment where this is hard to exploit. A good start would be to install the absolute minimal number of modules you have access to and constrain anything which allocates yourself, such as building your own vector or map abstractions suited for your need (unless you don't need them).

I've also punted on adding memory restrictions to the virtual machine due to not being able to implement it exhaustively without allocator_api, but we could add a limit to the stack. This is obviously far from enough though.

For now I generally only recommend running Rune on people's machines (like in their browser with WASM). Eventually when memory restrictions land, sandboxing will be a center stage feature.

udoprog commented 1 year ago

Note that it's not enough to statically limit the size of a container either, because you can just fill that container with maximally sized containers trivially breaking out of the restriction.

You'd have to both limit its size, and prevent large objects (large in bytes) from being added to it. That's why I wouldn't be comfortable implementing a solution unless it's holistic, like at the allocator level.

boehs commented 1 year ago

I understand that rhai likely suffers similarly. They have a similar budget solution: https://rhai.rs/book/safety/max-operations.html

There is also ways to limit the size of a string and sizes of arrays, which I suppose helps the memory situation somewhat, though I suppose there's nothing stopping people from

a = "a very large string... *almost* at the limit"
b = "a very large string... *almost* at the limit"
c = "a very large string... *almost* at the limit"
d = "a very large string... *almost* at the limit"
....

Thanks for this discussion, it's very enlightening

udoprog commented 1 year ago

Yeah, cheers.

You'd probably have to be a bit sneakier (due to string dedup, which I think rhai has?), but with loops enabled it's pretty easy to build large containers.