Is the Sandbox Safe?
Well, no. But yes! The sandbox does offer a stripped-down Ruby environment. Many of the normal Ruby constants and globals are missing. And classes like Thread, GC, IO and File are gone.
But, the sandbox is still vulnerable to some attacks. For instance, this endless ensure loop:
#!ruby
def endless
loop {}
ensure
endless
end
endless
The sandbox has a :timeout option for expiring a sandbox and it works on runaway code, but it can still be caught by ensure. So, this weakness still needs to be resolved.
Still, it's a good time to help me shake out the bugs and play with the classes. And, really, you can use your own process management to restart the sandbox should it start to consume resources.
Starting a Safe Sandbox
Like so:
#!ruby >> box = Sandbox.safe >> val = box.eval(unsafe_string)
Code passed into the sandbox has no access to the real Ruby environment. Even the value which eval passes back gets marshalled. So, if you're passing back a value, be sure that value's class is represented in your primary environment.
#!ruby
>> box.eval("class Test; end; Test.new")
ArgumentError: undefined class/module Test
from /opt/RUBY-1_8_5/lib/ruby/site_ruby/1.8/sandbox.rb:19:in `_eval'
from /opt/RUBY-1_8_5/lib/ruby/site_ruby/1.8/sandbox.rb:19:in `eval'
from (irb):4
However if Test is defined inside and outside of the Sandbox:
#!ruby
>> class Test; end
>> box.eval("class Test; end; Test.new")
=> #<Test:0x81c467c>
