$SAFE = 5 and Safe Ruby Misleading?

Well, what if I took in code, say from a semi-trusted source. Let’s say
an IRC bot (because I helped a friend write one). Originally, the bot
would have been able to accept strings from arbitrary users which would
be evaluated as Ruby. The strings would return some value. It was a
really interesting idea for such a lame domain.

But, you can’t do that. They don’t even have to modify core classes.
They need to modify one instance one one class. This is the case where
$SAFE = 4 is misleading. It also makes me wonder, what is the point of
it? If you can’t output from such a block in any way that wouldn’t risk
the integrity of the system, what does it DO? It seems to me the
PURPOSE of $SAFE = 4 is to make it so you can run untrusted code
without fear of it modifying the core environment.

For example, in the Programming Ruby book’s CGI example, what’s to say
that the string didn’t look innocuous, but return an object who’s
.to_html or .to_str didn’t just rm * again? I suppose with such a
simple expression, it’s easier, but more complex it would be
impossible.

Basically, can I evaluate something in a $SAFE = 4 thread, then get it
out and work with it meaningfully? The only way I can think of is to
try analyzing it in a $SAFE = 3 thread, where an object can’t untaint
itself, but doing so for an object would be pretty much impossible.

Anyone have any suggestions on how I mi

···

On Monday, August 11, 2003, at 4:35 PM, Brian Candler wrote:

So someone cannot send you a general Ruby object, unless you were to
explicitly unmarshal it, and they cannot directly touch your Ruby
run-time
environment. If they could, they could redefine ENV to return whatever
they
like, or they could simply override methods in your classes to do
whatever
they liked.


Dave Fayram
kirindave@lensmen.net
Developer / Idealist

Basically, can I evaluate something in a $SAFE = 4 thread, then get it
out and work with it meaningfully? The only way I can think of is to
try analyzing it in a $SAFE = 3 thread, where an object can't untaint
itself, but doing so for an object would be pretty much impossible.

No, the only way to do it is to make the analysis at $SAFE = 4 and return
an object with a known class.

Never try to interpret at a lower level the result of a block evaluated at
level 4.

You have an example of such mechanism in plruby (but it's written in
C). When plruby run with a timeout, it has 3 threads :
   * main thread (level 3)
   * timeout thread (level 3)
   * user thread (level 4)

All evaluations are made in the user thread, and the user thread must
return a valid object which is valided at level 4. The main thread never
try to evaluate some code, it just expect a valid object.

Guy Decoux

Hi,

Basically, can I evaluate something in a $SAFE = 4 thread, then get it
out and work with it meaningfully? The only way I can think of is to
try analyzing it in a $SAFE = 3 thread, where an object can’t untaint
itself, but doing so for an object would be pretty much impossible.

Not sure if this is sophisticated enough for your purpose - I just
needed arbitrary code to be evaluated “safely” at $SAFE = 4, and have
it be able to modify an object passed to it and return [some] result.

def safe_eval(_eval_str, *_args)
th = Thread.new(_eval_str, *_args) do |eval_str, *args|
res, warning = nil, nil
begin
$SAFE = 4
res = eval(eval_str)
rescue Exception => ex
warning = ex.to_s
end
[res, warning]
end
th.value
end

The calling code in my case is $SAFE = 1… not that the safe-level
of the calling code should matter, I believe.

For some reason, looking at my calling code, I wanted to pass in
a tainted object so it could be modified directly by the $SAFE = 4
thread via mutator methods (i.e. gsub!)… Though if one didn’t
want to allow any object passed to it to be modified, the evaluated
code could presumably dup the object, modify the copy, and return
the modified object as a result… (Unless that’s asking too much
of $SAFE = 4… I don’t remember )

Anyway what I’m doing is essentially:

some_object_to_be_modified.taint # allow mutator methods in high SAFE levels
res, warning = safe_eval(untrusted_code, some_object_to_be_modified)
if warning
log warning
log untrusted_code
end

Hope this helps,

Bill

···

From: “Dave Fayram” kirindave@lensmen.net

Hi,

Basically, can I evaluate something in a $SAFE = 4 thread, then get it
out and work with it meaningfully?

The untrusted thread can return value from it. For example,

def safe_eval(str)
Thread.start {
$SAFE=4
eval(str) # the last evaluated value
}.value # can be retrieved using “value” method
end

Besides, the thread can push data to the queue, then data is read by
the trusted code, validated, then output.

						matz.
···

In message “Re: $SAFE = 5 and Safe Ruby Misleading?” on 03/08/13, Dave Fayram kirindave@lensmen.net writes: