Python
The Python language design is very simple and clean. Amongst the security models of the three languages, Python's is the one I like the most. Python security model is capability-based, meaning that: if you don't want a certain code to be able to do stuff, you don't give a reference to the module/function that provide that stuff. Python is also much more modular: the core functionality is much less than that of Perl. For example, OS specific services--like unlink or rmdir--are located in the sys and os module. This means we can more easily restrict access to those services by depriving the code from importing the appropriate modules.
Here's Python's execution model: each code runs in a frame ("a context"). In a frame, there are two namespaces: the local and the global namespace. A namespace is a mapping between names and objects. You get reference (=capability) to objects from a namespace. Every time a variable/function/object/module name is mentioned, Python will look for it in the namespaces. The local namespace will be searched first, then the global. If the name is not found in either, Python will give a NameError exception.
We can manipulate a namespace easily, since it is available as a dictionary. We can even execute a code and give it our custom dictionaries to be used as the code's local and global namespaces. This way, we can limit what objects are available to the code. That's basically how the security model works in Python.
Actually, there's a third namespace that will be searched when a name is not found in a local and global namespace: the builtin namespace. The builtin namespace contains basic functions like open, exit, execfile. Most of the Python's builtin capabilities are provided through this builtin namespace. The rest is creatures like print or exec which are statements, not functions/objects.
rexec is the standard Python module to do sandboxing. It basically does what is explained above: run the sanboxed code with a custom local and global namespace. Additionally, rexec creates a custom builtin namespace and provides a safer substitutes for functions like open or __import__. This way, we can tell rexec to forbid the untrusted code from opening a file in write mode. Or from importing dangerous modules.
rexec is pretty flexible and indeed has been used successfully in several applications. Guido's web browser Grail, for instance, allows running Python applets. However, rexec seems to be not flexible or fine-grained enough, because Zope chooses not to use rexec. Instead, it uses its own home-growned module to do restricted execution.
There are several things that rexec can't do. Resource limiting, for example. To do that you need to resort to the OS (like using Unix's setrlimit). Also, since Python does not have private attributes, you can't give an object to an untrusted code without the fear that the code will use the Python reflection mechanism to "peek into the guts" of your object (and from there gain references to other objects). There are two separate solutions to the last problem: the Bastion and mxProxy C extension modules, which essentially provide private attributes.
Conclusion: Python has a nice and simple security model. However, rexec cannot do all kinds of isolation that one might need, like resource limiting. Guido once also said that rexec is not tested enough and it might contain security holes.
Ruby
One of the main goals of Ruby seems to be "to replace Perl". In that respect, it has copied many Perl features. Tainting is one of them. In Perl there are two running modes: tainting mode on (-T, setuid) and off (no -T). Ruby extends this concept a bit by providing four different "safe levels" (indicated by the global variable $SAFE). The different safe levels is as follows.
Safe level 0 (default mode): no tainting is performed.
Safe level 1: tainted data cannot be used to do potentially dangerous.
Safe level 2: in addition to level 1 restriction, program files cannot be loaded from a globally writable locations (e.g. from /tmp).
Safe level 3: in addition to level 2 restriction, all newly created objects are considered tainted.
Safe level 4: in addition to level 3 restriction, the running program is effectively partitioned in two. Nontainted objects may not be modified. Typically, this will be used to create a sandbox: the program sets up an environment using a lower $SAFE level, then resets $SAFE to 4 to prevent subsequent changes to that environment.
It's evident that, as with tainting, the safe levels are primarily concerned with data security and are not very sandbox-like (in the sense of "isolating subprocesses from another" sandbox). Matz confirmed this in the ruby-talk mailing list by saying that Ruby currently does not have any sandbox yet. Running a code in safe level 4 is usually too restrictive to be practical, plus it does not provide enough isolation.
The problem with isolation in Ruby is that all objects are accessible from any code through the ObjectSpace facility (including the code running in safe level 4). This is of course in direct conflict with the capability concept, in that you don't give a reference/capability unless necessary. However, Ruby does protect an object's attributes and has a #freeze method to make an object becomes read-only.
Conclusion: Ruby doesn't have a sandbox (yet).
Other PL's
Java has a sandbox security model and a bytecode verifier. Tcl basically has the same. Erlang is evolutionary more advanced in providing isolation, in that it has a notion of "PL-level processes" (a process is isolated in all ways from another).
Conclusion
As people construct more and more complex applications in PL, PL's are required to have adequate security/isolation mechanisms. Current PL's in mainstream usage do not have adequate security mechanisms, so programmers are often forced to fall back to using facilities provided by the OS. This has drawbacks such as lack of portability and reduced efficiency. There will perhaps be new PL's designed with isolation as one of their main goals--or current PL's might be improved/redesigned--so hopefully this requirement of having a "multiuser PL" will be fulfilled in the future.
About the Author:
Steven is a software developer residing in Bandung, Indonesia.
- "Intro, Isolation, Perl"
- "Python, Ruby, Conclusion"



