如何创建沙盒RSpec环境?

时间:2012-08-08 23:09:45

标签: ruby rspec jruby sandbox

基本上,我想创建一个程序来运行一些不受信任的代码来定义某个方法或类,然后对它运行一个不受信任的rspec规范。

我已经研究了一下沙盒Ruby,并且来自rubyconf的this video特别有帮助。在查看了几个解决方案后,看起来最有用的两个解决方案是rubycop,它基本上对代码进行静态分析,jruby sandbox(均在上面的视频中介绍)。我的直觉告诉我,犹豫不决的沙箱可能更安全,但我可能错了。

这是我想要做的完全不安全的例子:

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会很好。

2 个答案:

答案 0 :(得分:0)

看起来沙盒环境没有加载bundle / gemset。如果您使用gemset或其他东西,RVM可能会出现问题。

有人可能会尝试在装箱后再次加载Bundle。

我会看看红宝石污点模式

$SAFE   The security level
0 --> No checks are performed on externally supplied (tainted) data. (default)
1 --> Potentially dangerous operations using tainted data are forbidden.
2 --> Potentially dangerous operations on processes and files are forbidden.
3 --> All newly created objects are considered tainted.
4 --> Modification of global data is forbidden.

答案 1 :(得分:0)

我一直试图找出类似的问题。我想在激活它之后在我的沙盒中使用一些像json和rest-client这样的宝石。我试过跟随。

require "sandbox"
s=Sandbox.safe

s.eval <<-RUBY
  require 'bundler'
  Bundler.require :sandbox
RUBY

s.activate!

Gemfile.rb

group :sandbox do
  platforms :jruby do
    gem 'json'
    gem 'rest-client'
  end
end

通过这种方式,我可以在沙盒中使用宝石。但是,沙盒有一些特定于宝石的问题。例如,我必须在jruby-sandbox中为safe.rb添加一个方法initialize_dup到白名单。 RestClient与假文件系统ALT_SEPARATOR有一些问题,我试图修补。您可以尝试RSpec的这种方法,看看是否一切都通过。