Reputation: 2367
I have a Ruby on Rails app and I need to add some arbitrary 'functions' to the database. These functions need to receive predefined parameters, perform arbitrary logic and arithmetic, and return a number or a string.
My first idea was to add the code to the DB and use eval(code)
, but I soon realised the security issue with this. I could not find a way of a really sandboxed eval
.
I also thought about using a JavaScript interpreter, for example, to have the code in JS and run it it's own context, but it still seems a bit too much and not secure enough.
Is there a way to execute simple arbitrary logic and arithmetic from a string over some variables and return a value?
Upvotes: 0
Views: 171
Reputation: 2828
Run arbitrary code it is a unsafe practice and very difficult to ensure that you control all variables and different scenarios.
You can try to patch all Ruby classes/ modules that can run any malicious code, like IO, Kernel, etc, but in the end you will have many classes patched, very difficult to maintain and will not have sure if it will work safely.
The best solution that I can figure out is to create your own programming language where you can ensure all functions and operations that the user will have access.
Nowadays there are many solutions, paper and examples that makes this task not so difficult, for example Ragel http://www.complang.org/ragel/ that compiles to Ruby.
You can start with few operations (if, arithmetic, logic, etc) and improve it incrementally. In the end, you will have a robust solution that can easily evolve to fit on users needs.
Upvotes: 1
Reputation: 187004
How sophisticated does this code need to be? Or conversely, how arbitrary does it need to be? Hopefully, you don't need to store code.
Instead, keep code in your code, and data in your data. Then simply reference names of procedures. For example:
class User
def contact
case self.prefers_contact_method
when :email
Email.send_to self.email
when :sms
SMS.send_to self.mobile_number
when :call
Phone.place_call self.home_number
end
end
end
Putting executable code in your database is not a good idea. Avoid it at all costs. And if you really need to do it, then maybe you should rethink your approach.
And if you really really need to do this, you need a sandbox. Some environment where you can control what arbitrary code has access to so that there is no dangerous code that is possible to be executed. See: Ruby sandboxing vs. integrating a scripting language
But even so, it's a scary thing to open yourself up to. Tread very carefully with this, and think thoroughly through the security implications.
Upvotes: 0