你如何将Ruby Binding标记为可信?

时间:2010-09-01 15:08:31

标签: ruby multithreading trusted

从这篇文章http://www.stuartellis.eu/articles/erb引用线程安全级别:

“在此级别,必须将指定的绑定标记为受信任,以便ERB使用它。”

我搜索过高低,并没有找到一种方法将“绑定”标记为“可信任”。

有人请赐教我吗?

1 个答案:

答案 0 :(得分:9)

您应该通过调用taint方法污染绑定。

$SAFE级别是Ruby的一项功能,它会根据当前级别以及对象是否被污染来拒绝某些操作。假定污染字符串来自不受信任的来源,例如文件,数据库,HTTP客户端等。

例如,在$SAFE级别1,如果参数是受污染的字符串,Ruby将不允许您使用require个文件。

$SAFE 4级是最极端的。 Ruby将有效地禁止您修改任何未包含的对象。我们的想法是,您可以在应用程序中使用较低的$SAFE级别,并使用$SAFE级别4实例化线程或proc。在此沙箱中,您可以修改仅受污染的对象。

ERB使用此机制允许您在沙箱中运行模板。如果您尝试从某个绑定中获取渲染模板的结果,则会发生以下情况:

class TemplateContext
  def name; "Teflon Ted"; end
end

template_binding = TemplateContext.new.send(:binding)
ERB.new("Hi, <%= name %>!", 4).result(template_binding)

#=> SecurityError: Insecure: can't modify trusted binding

Blam!这是Ruby告诉你不能修改$SAFE级别4的非着色对象。它不允许你打电话具有给定绑定的eval(这正是ERB尝试的那样)。

相反,您应该为沙箱提供污染绑定。您明确告诉Ruby,在沙箱中使用此绑定是可以的,并且它不应该在沙箱之外被信任。

class TemplateContext
  def name; "Teflon Ted"; end
end

# Binding must be tainted!
template_binding = TemplateContext.new.send(:binding).taint
ERB.new("Hi, <%= name %>!", 4).result(template_binding)

#=> "Hi, Teflon Ted!"

有关Ruby $SAFE级别的更多信息,请参阅excellent description in the Pickaxe book