Playing With Fire: Running Uploaded Ruby Code in a Sandbox – David Stevenson

April 18, 2009 Chad Woolley

Playing With Fire: Running Uploaded Ruby Code in a Sandbox – David Stevenson

GoGaRuCo 09 - Playing With Fire: Running Uploaded Ruby Code in a Sandbox - David Stevenson


It is still new, but we will get a chance to interact with it live. There will be a competition to see who can compromise the sandbox first.

The prize is a Cupcake, but he has not bought it yet, because he doesn’t think anyone will break out.

Rules are you must break out of the sandbox itself, not compromise his box or the OS.

Why allow user code?

Say you want to make a decision about which folder to use for a user’s mail? You can write a bunch of complex rules, or you could allow your users to upload code to do it.

He makes a reference to the Neal Stephenson book about the Metaverse, where everyone uploads code.

Second Live also has a C metalanguage which allows players to create their own code and three-dimensional objects. In this type of game, the sky is the limit.

Google’s AppEngine is another example. Users can write their own code and run it in a sandbox, but Google handles all the scalability and hidden bits.

Why not allow user code?

Dangerous operations: Code could have errors, or not finish. Someone will upload an infinite loop almost immediately, you need to deal with it.

Knowledge: Are users programmers? Maybe they don’t want to learn a language, even one as easy and nice as Ruby.

API Manipulation: Maybe there are ways that users could manipulate your API in ways you have not even thought of yet…

What is a sandbox

  • Limited functionality
  • Can’t break out
  • Separate code space
    • There need to be separate code spaces – the user’s space is the “Jungle”
  • Bounded execution time


Freaky-freaky sandbox gem (MRI ruby): By why the lucky stiff with some contributions from David, written in C. It is a big hack, a bit of a disaster, but it works. We’ll get to play with it.

JavaSand gem (JRuby): Same API as Freaky-freaky, but not as much of a hack. JRuby provides more hooks into the internals, so you can do some of the same things that Freaky-freaky does, but without as much hackery and violation of internals.

Rubinius in the future? – Sub-virtual-machines could be used to create a sandbox, maybe even 20 lines of Rubinius. The C implementation is about 2000 lines.

Lets try it out

Expression Evaluator: 2+2 -> 4, etc.

He is creating the rails application from scratch, hopefully the bandwidth holds up. He’s not using Sinatra, because he doesn’t know how to get something scaffolded fast enough in the time constraints of a presentation.

Some dangerous things are NOT accessible in the sandbox, such as File and Kernel.

require 'test_helper'
require 'redgreen'

class ExprTest < ActiveSupport::TestCase
  test "two plus to equals four" do
    assert_equal 4, => "2 + 2").value
class Expr < ActiveRecord::Base
  def value

He then goes on to implement exception handling (test driven, of course), and also implements code to prevent infinite loops with a timeout.

He then wraps up the coding of the initial app, and he is exposing it to the audience. He has to do the standard rails stuff to make a new app work, delete index.html, set up routes, etc.

Now, the fun begins. Here’s some examples that are showing up within a minute:

  Listing exprs
  open testfile
  while true; end
  self.instance_eval{while true; end}
  `rm -rf ./'
  p=lambda { 'yo' };
  `sudo reboot`
  a = 2; a+3

  %x[tail log/production.log]
  while true; puts 'are we there yet'; end

  New expr

David is now discussing the restricted set of objects in the sandbox. The problem is that you need to reference things like Net::HTTP, but that is not in the set of restricted objects.

The solution is to reference some classes into the sandbox, and copy others. It runs the unsafe things “outside” of the sandbox, but users still cannot access these restricted classes.

Gem Support

  • acts_as_wrapped_class
  • acts_as_runnable_code
    • Set up the sandbox easily with referenced classes
    • Pass in top level binding and execute code

A Game! Hangman

# API methods
def word
def guesses
def guess!(char)
def all_words

There is a cron job. Every minute, all the algorithms run, and everyone can make a guess.

Reviewing the attempts to break out of the sandbox

Sorry, no backtick:

   Expr:  `rm -rf ./`

  Value: "#Sandbox::Exception: SyntaxError: (eval):3:in `_eval': compile errorn(eval):3: unterminated string meets end of file"

He then ask if anyone has broken out of the sandbox. NO hands go up. Win! Everyone claps. Great preso!

About the Author


GoGaRuCo '09 – TrustTheVote: Open Source Digital Voting – Gregory Miller
GoGaRuCo '09 – TrustTheVote: Open Source Digital Voting – Gregory Miller

Links Open Source Digital Voting Trust The Vote What OSDV means to me personally I personally am really...

GoGaRuCo '09 – Sinatra: The Framework Within – Aaron Quint
GoGaRuCo '09 – Sinatra: The Framework Within – Aaron Quint

Aaron starts out with a really bad joke about 'eyhelp', which puts him in good standing with me, at least (...