# Code execution from file?

**URL:** <https://www.ruby-forum.com/t/code-execution-from-file/49721>\
**Category:** Ruby\
**Created:** [December 8, 2005, 12:38am UTC](https://www.ruby-forum.com/t/code-execution-from-file/49721 "2005-12-08T00:38:16Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![akonsu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/13edae/32.png) [@akonsu](https://www.ruby-forum.com/u/akonsu)\
**Post date:** [December 8, 2005, 12:38am UTC](https://www.ruby-forum.com/t/code-execution-from-file/49721/1 "2005-12-08T00:38:16Z")

</div>

hello,

i have a text field in a database table (a text file, generally  
speaking), with arbitrary Ruby code. i would like to execute this code  
in my application’s current environment. but i need to hide all my  
variables except for some specific ones from this code.

so i was thinking to create a class with a static method that accepts  
parameters and put the content of the file in to this method. and pass  
the variables i want to expose as parameters.

how is this done in ruby? i have never done it.

in addition, how to execute this code with maximal security level?

also, what would happen if the code reopened classes that i have  
created? is this possible? how to make it not do that?

basically i want the user to type some code in to my application and  
run it but i want to protect against malicious users who want to erase  
my hard disk, etc. 😉

thanks for any help!  
konstantin

---

<div class="post-metadata">

**Author:** ![akonsu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/13edae/32.png) [@akonsu](https://www.ruby-forum.com/u/akonsu)\
**Post date:** [December 8, 2005, 12:46am UTC](https://www.ruby-forum.com/t/code-execution-from-file/49721/2 "2005-12-08T00:46:24Z")

</div>

please forgive the term “class with a static method”, i meant “class  
with a class method”. my brain is still in this c++/java/c# rut.

---

<div class="post-metadata">

**Author:** ![akonsu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/13edae/32.png) [@akonsu](https://www.ruby-forum.com/u/akonsu)\
**Post date:** [December 8, 2005, 2:24am UTC](https://www.ruby-forum.com/t/code-execution-from-file/49721/3 "2005-12-08T02:24:02Z")

</div>

On Thu, 8 Dec 2005, ako… wrote:

> how is this done in ruby? i have never done it.
> 
> in addition, how to execute this code with maximal security level?
> 
> also, what would happen if the code reopened classes that i have created? is  
> this possible? how to make it not do that?
> 
> basically i want the user to type some code in to my application and run it  
> but i want to protect against malicious users who want to erase my hard  
> disk, etc. 😉

```
 harp:~ > cat a.rb
 def run file, vars = {}
   code = IO::read file
   dumped = vars.inject({}){|d,kv| k, v = kv; d.update k => 

```

Marshal::dump(v)}  
Thread::new(vars, code) do |vars, code|  
$SAFE = 4  
program = “”  
dumped.each{|k,v| program \<\< “#{ k } = Marshal::load  
\<\<- **data** \n#{ v }\n\_\_data\_\_\n\n”}  
program \<\< code  
eval program  
end.value  
end

```
 value = run "b.rb", "a" => "forty-two"
 p value

 value = run "c.rb", "a" => "42"
 p value

 harp:~ > cat b.rb
 a.upcase

 harp:~ > cat c.rb
 a.center 42

 harp:~ > ruby a.rb
 "FORTY-TWO"
 " 42 "

```

hth.

-a

---

<div class="post-metadata">

**Author:** ![akonsu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/13edae/32.png) [@akonsu](https://www.ruby-forum.com/u/akonsu)\
**Post date:** [December 8, 2005, 4:09am UTC](https://www.ruby-forum.com/t/code-execution-from-file/49721/4 "2005-12-08T04:09:21Z")

</div>

There are a number of mechanisms to “lock down” the execution for a  
chunk of Ruby code, the most common being the built-in $SAFE global  
variable. Unfortunately, due to a number of recently-published  
vulnerabilities in the implementation of the $SAFE checks, it’s  
generally not considered a good way to insure that your application  
will be protected from malignant users.

The best example I’ve seen to date of a truly safe Ruby interpreter has  
to be why the lucky stiff’s “Try Ruby” website  
([http://tryruby.hobix.com/](http://tryruby.hobix.com/)), which lets anyone interact with a  
restricted IRb prompt via their browser and some slick Javascript. You  
might email why\_ directly, and see if he’d be willing to share some  
tips with you (and the rest of us!).

At a bare minimum, you need to make sure the following built-in classes  
and modules are either entirely hidden, or redefined to “safe”  
versions:

Dir  
File  
FileStat  
FileUtils  
IO (at least methods like ‘popen’, ‘fcntl’, etc.)  
ObjectSpace  
Pathname  
Process  
GzipFile  
Kernel (‘fork’, ‘at\_exit’, ‘caller’, ‘load’, ‘require’, many more)

…and probaby others, as well. Really, it’s a _hard_ thing to make  
arbitrary code execution safe, so unless you can re-use and share  
effort with others, I’d caution you against doing this unless  
absolutely necessary.

Good luck,

Lennon

---

<div class="post-metadata">

**Author:** ![akonsu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/13edae/32.png) [@akonsu](https://www.ruby-forum.com/u/akonsu)\
**Post date:** [December 8, 2005, 3:49am UTC](https://www.ruby-forum.com/t/code-execution-from-file/49721/5 "2005-12-08T03:49:02Z")

</div>

thank you very much for your help.

my application runs inside a web browser process, and creating a thread  
does not seem scalable.

i tried to evaluate a file from inside a lambda and it seems to work. i  
also was able to set safety level for lambda locally which effectively  
restores $SAFE when lambda finishes. the only drawback of this was that  
my environment is still visible from lambdas.

code = \<\<CODE  
v = MyClass.new(‘from text’)  
v.mymethod  
CODE

class MyClass  
def initialize(v) @v = v end  
def mymethod() puts “SAFE=#{$SAFE}, value=#{@v}” end  
end

p = eval \<\<LAMBDA  
lambda {  
module Mod  
$SAFE = 3  
#{code}  
end  
}  
LAMBDA

v = MyClass.new(‘original’)  
v.mymethod  
p.call  
v.mymethod

---

<div class="post-metadata">

**Author:** ![akonsu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/13edae/32.png) [@akonsu](https://www.ruby-forum.com/u/akonsu)\
**Post date:** [December 8, 2005, 8:53am UTC](https://www.ruby-forum.com/t/code-execution-from-file/49721/6 "2005-12-08T08:53:50Z")

</div>

putting aside security issues i think i was able to isolate my  
environment and pass only desired variables in to the code. i create a  
temporary module and evaluate my code in its context. then i remove  
this module (that is why i needed the external module A, i could not  
figure out how to remove a module otherwise). experts, does this look  
feasible? i do not know though what to do to ensure security…

thanks  
konstantin

module A  
x = ‘x’  
y = ‘y’

module T  
class \<\< self  
def get\_binding§ binding end  
end  
end

# eval(‘puts x’, T.get\_binding(x)) -\> # fails

puts eval(’“variable #{p}”’, T.get\_binding(x))

remove\_const :T

#puts eval(’“variable #{p}”’, T.get\_binding(x)) -\> # fails  
end

---

<div class="post-metadata">

**Author:** ![akonsu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/13edae/32.png) [@akonsu](https://www.ruby-forum.com/u/akonsu)\
**Post date:** [December 8, 2005, 7:39pm UTC](https://www.ruby-forum.com/t/code-execution-from-file/49721/7 "2005-12-08T19:39:26Z")

</div>

is there a way in ruby to set up a hook that would intercept calls to  
any methods of a class?

---

<div class="post-metadata">

**Author:** ![akonsu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/13edae/32.png) [@akonsu](https://www.ruby-forum.com/u/akonsu)\
**Post date:** [December 8, 2005, 4:41am UTC](https://www.ruby-forum.com/t/code-execution-from-file/49721/8 "2005-12-08T04:41:51Z")

</div>

On Thu, 8 Dec 2005, ako… wrote:

> thank you very much for your help.
> 
> my application runs inside a web browser process, and creating a thread does  
> not seem scalable.

but what if the user code creates one? it’s the only way to isolate  
$SAFE and  
your vars, see below…

> i tried to evaluate a file from inside a lambda and it seems to work. i also  
> was able to set safety level for lambda locally which effectively restores  
> $SAFE when lambda finishes. the only drawback of this was that my  
> environment is still visible from lambdas.

also note that lambda will prevent **everything** in it’s scope from  
**ever**  
being garbage collected. this is bad idea in a web app - assuming it’s  
persistant like fastcgi.

in any case be careful:

```
 harp:~ > cat a.rb
 code = IO::read "b.rb"

 p = eval <<LAMBDA
    lambda {
    module Mod
    $SAFE = 3
    #{code}
    end
    }
 LAMBDA

 p.call
 p "we won't see this!"

 harp:~ > cat b.rb
 exit!

 harp:~ > ruby a.rb

```

a thread will prevent you main program from exiting.

regards.

-a

---

<div class="post-metadata">

**Author:** ![akonsu](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/13edae/32.png) [@akonsu](https://www.ruby-forum.com/u/akonsu)\
**Post date:** [December 9, 2005, 2:17pm UTC](https://www.ruby-forum.com/t/code-execution-from-file/49721/9 "2005-12-09T14:17:52Z")

</div>

The Facets library has a lot of cool methods,  
one of which (‘wrap\_method’) can intercept calls.

[http://facets.rubyforge.org/rdoc/index.html](http://facets.rubyforge.org/rdoc/index.html)
