From: Tim Bates Date: 2003-01-10T17:42:11+09:00 Subject: Security problems I'm having problems with controlling what can and can't be done in a certain piece of code. As some of you will be aware, I'm working on a Ruby implementation of RoboCode, the ephemeral programming game. The robots and controller are being written in Ruby (what else?) and I'm loading the robots into the controller's code directly by use of eval. To prevent the robots doing anything nasty to the controller, the other robots or the system the program is running on, all robot code is being executed with $SAFE == 4. This is necessary as, among other things, it prevents them from modifying untainted objects. So reducing $SAFE is not an option. As Ruby is an extremely object-oriented language, and as part of the aim of the program is to provide a teaching tool for Ruby and/or OOP, the robot API is planned to be simple - extend a pre-written Robot class and add some pre-defined methods (eg MyRobot#run) to do whatever you want. The problem is that with $SAFE == 4, it doesn't allow the robot programmer to create new classes ("SecurityError: Insecure: can't set constant"), and I can't just create the class for them first and give it to them to modify either ("SecurityError: extending class prohibited") The only way I can get around this is by creating a temporary module and extending the robot with it outside of $SAFE == 4: eval <<-END module Ex#{__id__} self.taint @f = File.readlines(sourcefile).join.untaint safe(4) { eval(@f, binding, sourcefile) } end self.extend Ex#{__id__} END However this destroys the OOP-style extend-the-robot-class API, and thus removes some of its usefulness as a Ruby teaching tool. Can anyone else see a way around this? Running the code in a separate process (like RealTimeBattle does) is not really an option either, because it would still allow malicious code to damage the system on which it is run, and it would reduce the ability run tournaments etc safely. Tim Bates -- tim@bates.id.au