Forum: Ruby is an unsafe binding context that does not close over anything, actually safe

Posted by Mean L. (mean_l)
on 2012-10-14 11:28
def context_binding
  @context.instance_eval {binding}
end

def eval(str)
  ->{$SAFE = 4; context_binding.eval(str)}.()
end

the binding context is unsafe since it's constructed in the sandbox

but since it appears to not close over anything other than self
(@context) which is safe, is it then effectively safe?
Posted by Robert Klemme (robert_k78)
on 2012-10-14 19:06
(Received via mailing list)
On Sun, Oct 14, 2012 at 11:28 AM, Mean L. <lists@ruby-forum.com> wrote:
> def context_binding
>   @context.instance_eval {binding}
> end
>
> def eval(str)
>   ->{$SAFE = 4; context_binding.eval(str)}.()
> end
>
> the binding context is unsafe since it's constructed in the sandbox

What exactly do you mean by "safe" here?  Can you be more specific
what you mean by "safety" here and what you are trying to accomplish?

> but since it appears to not close over anything other than self
> (@context) which is safe, is it then effectively safe?

The safety of the whole thing depends on str's tainted status it
seems.  Also, since you are not executing the code in its own thread
you create a side effect with your change of $SAFE.  The usual
solution to this is to use $SAFE in another thread.  You could do

def e(str)
  Thread.new do
    $SAFE  = 4
    context_binding.eval(str)
  end.value
end

This wastes a single thread but doesn't actually execute in parallel
because via Thread#value the caller thread blocks until the other
thread has finished.  And you do not change the $SAFE status of the
caller which IMHO is a bad side effect to have.

Kind regards

robert
Posted by Mean L. (mean_l)
on 2012-10-14 19:48
Robert Klemme wrote in post #1079785:
> On Sun, Oct 14, 2012 at 11:28 AM, Mean L. <lists@ruby-forum.com> wrote:
>> def context_binding
>>   @context.instance_eval {binding}
>> end
>>
>> def eval(str)
>>   ->{$SAFE = 4; context_binding.eval(str)}.()
>> end
>>
>> the binding context is unsafe since it's constructed in the sandbox
>
> What exactly do you mean by "safe" here?  Can you be more specific
> what you mean by "safety" here and what you are trying to accomplish?
>

I meant to use the term (un)trusted. The concept of trust is well 
defined in ruby. (untrusted code not being to modify trusted objects. 
Object#untrused?).

So, to clarify and expand, my biding is untrusted because it's 
constructed in the $SAFE=4 sandbox.  Which means the untrusted sandbox 
code can modify it.  So the question is, am I correct that in my usage, 
the binding does not close over anything (other than self which refers 
to a trusted object) so does not allow to modify anything, which in 
effect makes it as if trusted.

>> but since it appears to not close over anything other than self
>> (@context) which is safe, is it then effectively safe?
>
> The safety of the whole thing depends on str's tainted status it
> seems.  Also, since you are not executing the code in its own thread
> you create a side effect with your change of $SAFE.  The usual
> solution to this is to use $SAFE in another thread.  You could do
>
> def e(str)
>   Thread.new do
>     $SAFE  = 4
>     context_binding.eval(str)
>   end.value
> end
>
> This wastes a single thread but doesn't actually execute in parallel
> because via Thread#value the caller thread blocks until the other
> thread has finished.  And you do not change the $SAFE status of the
> caller which IMHO is a bad side effect to have.

Here's what "programming ruby" says about that:

"The safe level
may be set during the execution of a proc object without affecting the 
safe level of the code that
invoked that proc."

Experimentally that appears to be true.  $SAFE remains 0 after the 
lambda runs.
Posted by Mean L. (mean_l)
on 2012-10-19 15:12
def context_binding
  @context.instance_eval {binding}
end

def eval(str)
  ->{$SAFE = 4; context_binding.eval(str)}.()
end


 So, to clarify and expand, my biding is untrusted because it's
 constructed in the $SAFE=4 sandbox.  Which means the untrusted sandbox
 code can modify it.  So the question is, am I correct that in my usage,
 the binding does not close over anything (other than self which refers
 to a trusted object) so does not allow to modify anything, which in
 effect makes it as if trusted.


Is there a more appropriate list for this question?
Posted by Bartosz Dziewoński (matmarex)
on 2012-10-19 17:05
(Received via mailing list)
2012/10/19 Mean L. <lists@ruby-forum.com>:
> Is there a more appropriate list for this question?

I don't think there is. Unfortunately, just about no one uses this
feature, so no one can really help; all I can suggest is not using it
as well or experimenting.

-- Matma Rex
Posted by Mean L. (mean_l)
on 2012-10-19 17:49
Bartosz Dziewoński wrote in post #1080460:
> 2012/10/19 Mean L. <lists@ruby-forum.com>:
>> Is there a more appropriate list for this question?
>
> I don't think there is. Unfortunately, just about no one uses this
> feature, so no one can really help; all I can suggest is not using it
> as well or experimenting.
>
> -- Matma Rex

def context_binding
  @context.instance_eval {binding}
end

What feature are you referring to?  The question is about #binding and 
what it captures and gives access to in my usage.  AFAICT it's only self 
of @context and nothing else.
Posted by Bartosz Dziewoński (matmarex)
on 2012-10-19 18:37
(Received via mailing list)
I'm referring to $SAFE.

-- Matma Rex
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.