From: Garthy D Date: 2011-12-19T10:13:42+09:00 Subject: Re: Ruby, SAFE, method interception, and plugins Hi Gary, On 19/12/11 10:31, Gary Wright wrote: > I'm not sure that I would want to rely on any language enforced constraints for executing 'hostile' code within the same address space as my main application. I think a better solution is to run the foreign code (that sounds nicer) in an external process or even on a completely separate system and then use some sort of communication scheme to interact with the foreign code. If the communication scheme is well defined it also means that the plugin doesn't have to even be in Ruby. > > If you want to run it on the same system but in a different process you can arrange for the process to be 'locked down' in a sandbox or other restricted environment. The specifics on how to do this are going to be very dependent on your production environment but perhaps someone will pipe up with some specific suggestions > if you tell us about your environment. I'll give it a shot. :) I am developing a cross-platform app, Linux and Windows initially. Using Ruby code for plugins is extremely desirable as much of the app itself is already written in Ruby, and I don't want the users to even have to consider the platform. Most users would only be using a single platform anyway, and many plugin authors would be new to Ruby. From the perspective of a potential plugin, I would be providing the entire interface- every call that they could need to interact with the app would be provided. As mentioned, it could be as simple as message passing between a couple of objects. In fact, I don't want the plugin to be able to communicate outside the app, except through the API provided by the app. This includes networking, filesystem access, and the like. I would most likely supply a "require" replacement as well, and RubyGems or existing libraries wouldn't be directly usable. I would like plugin authors to be able to use things such as strings, arrays, create an manage their own custom classes, so forth. I could potentially whitelist allowed things if I could hook into things at various points. Plugin authors would *generally* not be deliberately malicious, because they won't be entirely anonymous (as per if it was a online web app, for example), but it could happen, so I'd like to minimise the interactions with the external environment as much as possible. Some authors will be genuinely curious and be looking to explore the rest of the Ruby code that is running. I specifically want to limit this. A determined attacker will of course eventually succeed, but I want to make it difficult. The app users would be the ones running the plugins. Most wouldn't be able to write a line of Ruby to save their lives, let alone understand plugins as anything more than a magic file they download. Thus, if they enabled a plugin that executed 99999999**999999999, it might lock the app up, but they'll just kill it, restart it, and not use the dodgy plugin next time. If the plugin was capable of blasting files away from their filesystem, then there is a problem. Thus maliciousness that causes an app crash is only a minor problem, maliciousness that deletes files is a big problem. As most of the interaction would be in the form of method calls (ie. plugin calls app, expects a return value, app call plugin, expects a return value), a separate process for the app would be cumbersome. A separate thread would be slightly annoying, and in the same thread would be fine. However, I realise that the closer the plugin gets to the app in this way, the harder it will be to sandbox. My gut feeling is that the solution would probably be provided at the (Ruby) thread level. The current state of the code is that the app is still in development, but many of the basics are in there. No plugin infrastructure exists yet, as I'm just starting to explore the possibilities (hence the reason for my post- I'm trying to figure out the best place to begin). The app itself is a C++ and embedded Ruby mix, and I've worked with both for the last decade or so. Patching the version of Ruby I am using myself is a possibility if it helps, as I'm fine building Ruby and potentially making very small changes. I am using the 1.9 series. I'm happy answer any questions on specifics if it helps. Garth