A Ruby execution sandbox. It executes a code block at a given $SAFE level and handles the security of the context the code will operate on. Unsafe operations will raise a SecurityError. See www.ruby-doc.org/docs/ProgrammingRuby/html/taint.html for more information on $SAFE levels.
Sandboxed provides two methods directly in the Kernel module for convenience.
safe do do_something end safe_method :my_method
A simple example would be a program that executes a line from STDIN.
require 'sandboxed' code = gets.untaint puts safe{ eval(code) }
Per default, code will be executed at $SAFE=4. To change this, use the :level option.
safe(:level => 3) { ... }
You can also set the context which the given code block will operate on.
safe(:context => 'foo') { reverse } # => "oof"
Local variables are automatically passed into the safe block.
foo = "foo" safe{ foo.reverse } # => "oof"
Even though they are accessible, unsave operations on them are prevented.
arr = [] safe{ arr << 'foo' } # => SecurityError
To perform unsafe operations on them, you have to untrust them.
arr.untrust safe{ arr << 'foo' } # => ["foo"]
Per default, Sandboxed uses :overlay mode, which prevents For Ruby 1.8.7 or higher, :ctx_only mode is available. This means only the context is available to unsafe code. In case you want to publish local variables to the safe block, you have to pass them as parameters.
bar = 'bar' safe(bar, :context => 'foo', :mode => :ctx_only) { |bar| bar + reverse } # => "baroof"
If you want to have :ctx_only ad the default mode for your application, you can do so.
Sandboxed.default_mode = :ctx_only
Some methods on your context might (intentionally!) raise a SecurityError when called in a safe environment.
class MyContext def log(text) puts text # would raise a SecurityError on $SAFE=4 end safe_method :log # this makes it safe to call end ctx = MyContext.new safe(:context => ctx) do log "something important" end
Sandboxed was successfully tested on MRI and REE >= 1.8.6. JRuby does not support $SAFE levels, so we’re pretty much out of luck. Same seems to be the case with Rubinius.
Test results and patches for other environments are greatly appreciated!
You can install Sandboxed via rubygems.
gem install sandboxed
Or you can use Bundler.
echo "gem 'sandboxed'" >> Gemfile bundle install
That way, you can easily switch to the bleeding edge directly from the github repository.
gem 'sandboxed', :git => 'git://github.com/QaDeS/sandboxed.git'
For bug reports and feature requests, use the github tracker at github.com/QaDeS/sandboxed/issues
If you want to get your hands dirty, please fork the project at github.com/QaDeS/sandboxed
Copyright © 2011 Michael Klaus. See LICENSE for details.