Ruby: creating a sandboxed eval?
You might want to check the 'taint' method and related stuff. This is a good reference:
http://ruby-doc.com/docs/ProgrammingRuby/html/taint.html
Despite that, I can't advise you enough against storing code and evaluating it, it's a security risk that should be avoided and most times there's a simpler way of solving your problems.
If you need to evaluate complex rules and predicates I'd recommend a rule engine to create a nice DSL. Haven't used one in ruby but this one looks good to me:
http://treetop.rubyforge.org/index.html
Cheers
How to run untrusted Ruby code inside a safe sandbox?
$SAFE is not enough; you need to be at least at the level of Why's freaky sandbox. However, I don't know if that sandbox code is actively maintained or if he/they ever solved the holes such as infinite loops, etc.
Unsafe generally means hostile. If you can relax from hostile to, say, 'naive', and depending upon the requirements of your app, you might get away with sandboxing in Ruby. It's not really a first-class scenario in the language design.
Even with that, though, you probably don't need to go to the machine level of separation. I'd feel pretty safe using a sandbox in a separately spawned process, with your app functioning as a process manager to kill off any that manage to hang/flame. Now, that is a few orders of magnitude more work than your simple block above.
But remember and keep repeating, "SAFE can't deal with hostile".
Executing arbitrary functions in Ruby without the security problems of eval
Run arbitrary code it is a unsafe practice and very difficult to ensure that you control all variables and different scenarios.
You can try to patch all Ruby classes/ modules that can run any malicious code, like IO, Kernel, etc, but in the end you will have many classes patched, very difficult to maintain and will not have sure if it will work safely.
The best solution that I can figure out is to create your own programming language where you can ensure all functions and operations that the user will have access.
Nowadays there are many solutions, paper and examples that makes this task not so difficult, for example Ragel http://www.complang.org/ragel/ that compiles to Ruby.
You can start with few operations (if, arithmetic, logic, etc) and improve it incrementally. In the end, you will have a robust solution that can easily evolve to fit on users needs.
Ruby\Rails sandboxing
My problem was not so hard to solve without any gems. The idea is that you have whitelist of methods and constants WHITELIST
and this class checks, if all methods and constants are in the whitelist
# gem install 'parser'
require 'parser/current'
class CodeValidator
attr_reader :errors, :source
WHITELIST = {:send => [:puts, :+, :new], :const => [:String]}
class Parser::AST::Node
def value
return children[1] if [:send, :const].include? type
fail NotImplementedError
end
end
def initialize(source)
@errors = []
@source = source
end
def valid?
!insecure_node?(root_node)
end
private
def exclude_node?(node)
blacklisted_node_types.include?(node.type) && !WHITELIST[node.type].include?(node.value)
end
def blacklisted_node_types
WHITELIST.keys
end
def insecure_node?(node)
return !!add_error_for_node(node) if exclude_node?(node)
node.children.each { |child_node| return true if child_node.class == Parser::AST::Node && insecure_node?(child_node) }
false
end
def root_node
@root_node ||= Parser::CurrentRuby.parse source
end
def add_error_for_node(node)
errors << "#{node.type} not allowed: #{node.value}"
end
end
c = CodeValidator.new("s = 'hello ' + String.new('world'); puts s.inspect")
p c.valid? # => false
p c.errors # => ["send not allowed: inspect"]
Ruby sandboxing vs. integrating a scripting language
You might consider using the Shikashi gem, which allows you to create sandboxes and define a whitelist of allowed method calls on individual objects.
Related Topics
What Does "Shadowing" Mean in Ruby
How to Check the Database Type in a Rails Migration
How to Test CSV File Download in Capybara and Rspec
What's the Point of Freezing Your Rails Version/Gems
Create a Daemon with Double-Fork in Ruby
Building Ruby with Rbenv and Ruby-Build Fails with Undefined Symbol: Sslv2_Method
What's the Point of the Prefix? Operator in Ruby 1.9
Is It Ok to Use 'Any' to Check If an Array Is Not Empty
Rails 3.1 Absolute Url to an Image
How to Convert a Ruby Object to JSON
How to Test 'Rand()' with Rspec