How do you mark a Ruby Binding as trusted?
Asked Answered
C

1

5

From this article http://www.stuartellis.eu/articles/erb referring to thread safety levels:

"At this level, the specified binding must be marked as trusted for ERB to use it."

I've searched high and low and haven't found a way to "mark" a Binding as "trusted".

Will somebody please enlighten me?

Calotte answered 1/9, 2010 at 15:8 Comment(0)
C
9

You should taint the binding by calling the taint method.

The $SAFE levels are a feature of Ruby that denies certain actions depending on the current level and whether an object is tainted. Tainted strings are assumed to originate from an untrusted source, such as a file, a database, a HTTP client, etc.

At $SAFE level 1, for example, Ruby will not allow you to require files if the argument is a tainted string.

$SAFE level 4 is the most extreme. Ruby will effectively disallow you to modify any nontained object. The idea is that you can use a lower $SAFE level in your application, and instantiate a thread or proc with $SAFE level 4. Within this sandbox, you can modify tainted objects only.

ERB uses this mechanism to allow you to run a template within a sandbox. If you try to get the result of a rendered template from a certain binding, this is what happens:

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! This is Ruby telling you that it is not okay to modify a nontainted object at $SAFE level 4. It will not allow you to call eval with the given binding (which is exactly what ERB attempts).

Instead, you should provide the sandbox with a tainted binding. You are explicitly telling Ruby that it is okay to use this binding in a sandbox, and that it should not be trusted outside the sandbox.

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!"

For more information about Ruby's $SAFE level, see the excellent description in the Pickaxe book.

Canton answered 2/9, 2010 at 11:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.