基本上,我想创建一个程序,运行一些不受信任的代码来定义一些方法或类,然后运行一个不受信任的rspec规范来测试它。
我已经研究了一些关于Ruby沙箱的资料,其中this video来自rubyconf非常有帮助。在查看了几种解决方案后,似乎最有用的两种是rubycop,它基本上对代码进行静态分析,以及jruby sandbox(以上视频都有介绍)。我的直觉告诉我jruby沙箱可能更安全,但我可能错了。
这里是一个完全不安全的例子:
那段代码抛出了这个异常:
这是因为RSpec在沙盒被锁定后尝试要求一些内容。因此,我尝试通过调用一个空的
这基本意味着在沙盒中不存在
可能是与宝石和这个特定的沙盒有关的问题。沙盒对象实际上支持一个
看起来使用这个沙盒可能真的不太可能与rspec一起使用。主要问题是尝试将其加载到沙盒中。我甚至尝试过这样的事情:
我已经研究了一些关于Ruby沙箱的资料,其中this video来自rubyconf非常有帮助。在查看了几种解决方案后,似乎最有用的两种是rubycop,它基本上对代码进行静态分析,以及jruby sandbox(以上视频都有介绍)。我的直觉告诉我jruby沙箱可能更安全,但我可能错了。
这里是一个完全不安全的例子:
code = <<-RUBY
class Person
def hey
"hey!"
end
end
RUBY
spec = <<-RUBY
describe Person do
let(:person) { Person.new }
it "says hey" do
person.hey.should == "hey!"
end
end
RUBY
# code and spec will be from user input (unsafe)
eval code
require 'rspec/autorun'
eval spec
这一切都很好,但显然需要对代码进行沙箱处理。很快就会有一些天才提交 system("rm -rf /*")
、fork while fork
或其他同样危险的代码。
我曾经尝试使用jruby沙箱……
sand = Sandbox::Safe.new
sand.eval("require 'rspec/autorun'")
sand.activate! # lock it down
sand.eval code
puts sand.eval spec
那段代码抛出了这个异常:
Sandbox::SandboxException: NoMethodError: undefined method `require' for #<RSpec::Core::Configuration:0x7c3cfaab>
这是因为RSpec在沙盒被锁定后尝试要求一些内容。因此,我尝试通过调用一个空的
describe
来强制RSpec在沙盒被锁定之前要求内容。sand = Sandbox::Safe.new
sand.eval("require 'rspec/autorun'")
sand.eval("describe("") { }")
sand.activate! # lock it down
sand.eval code
sand.eval spec
我得到了这个:
Sandbox::SandboxException: NameError: uninitialized constant RSpec
这基本意味着在沙盒中不存在
RSpec
。这很奇怪,因为sand.eval("require 'rspec/autorun'")
返回true,并且之前的示例实际上可以工作(RSpec的自动加载程序开始运行)。可能是与宝石和这个特定的沙盒有关的问题。沙盒对象实际上支持一个
#require
方法,它本质上绑定到Kernel.require
,因此无法加载宝石。看起来使用这个沙盒可能真的不太可能与rspec一起使用。主要问题是尝试将其加载到沙盒中。我甚至尝试过这样的事情:
require 'rspec'
sand.ref(RSpec) # open access to local rspec
但它并没有接受这一点。
所以,我的问题有两个方面:
- 有人有什么聪明的想法来让它在jruby沙盒中工作吗?
- 如果没有,rubycop有多安全?显然codeschool使用它,所以它必须经过很好的测试...能够使用Ruby 1.9而不是jruby将是不错的选择。