Open boehs opened 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.
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.
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.
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
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.
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
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?