如何创建一个沙盒化的 RSpec 环境?

5
基本上,我想创建一个程序,运行一些不受信任的代码来定义一些方法或类,然后运行一个不受信任的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将是不错的选择。
2个回答

0

看起来沙盒环境没有加载bundle/gemset。如果您正在使用gemset或其他内容,则可能是RVM的问题。

一旦沙盒化,可以尝试重新加载Bundle。

我会查看Ruby污点模式。

$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.

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

通过这种方式,我能够在我的沙盒中要求宝石。但是,然后出现了一些与沙盒相关的宝石问题。例如,我不得不添加一个名为initialize_dup的方法到jruby-sandbox中的safe.rb白名单中。RestClient在虚拟文件系统ALT_SEPARATOR上存在一些问题,我正在尝试修补它。您可以尝试使用此方法进行RSpec测试,并查看是否一切顺利。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接