Version 2 of Safe Interps

Updated 2002-09-29 05:55:14

A page to discuss the usefulness of safe interps, and things related (such as what to ensure about your extension to make it 'safe' (see also the safe command.

I'm starting this page with a very informative post from The comp.lang.tcl newsgroup by Jacob Levy. Feel free to add more!


29Sep02 Jacob Levy:

The motivation of this discussion is whether adding a SafeInit C procdure to Itcl is justified based on the grounds of security evaluation. I think this discussion applies equally to any C extension. I also explain below why it is safe to add any Tcl-only extension to a safe slave interpreter.

To start with, anything available in a safe slave interpreter (when it is first created) is safe for that interpreter. Note that I said "available", hidden functions (ones whose name is given in a call to "interp hide") are not available in the safe interpreter. All dangerous stuff like "exec" and "source" is hidden by "interp create -safe". After that, if the user does not add native code packages or "interp expose" or "interp alias", then the interpreter stays safe. The interpreter stays safe even if you do these things, but carefully. The master interpreter is able to relax security to a degree, under its control, by making more functionality available in the slave safe interpreter through aliases.

In general, a native code package should not violate this rule, so a slave safe interpreter should be as safe with the functionality of this package as it is without it. For more relaxed security, use security policies first introduced with the Tcl plugin. Note that by design, if the package is written in 100% Tcl code it is safe because all Tcl primitives that are unsafe are not available in the safe slave interpreter and thus it matters nought if the code tries to use them; the call will just fail.

So the question to be asked by a security review of Itcl is: is Itcl safe enough so that it can be added to a safe interpreter and not compromise the base security policy provided by "interp create -safe". If not, you should write some other mechanism that only allows adding Itcl to the safe slave under control of an explicit security policy. Of course as Itcl provides functionality implemented by native code, that mechanism is going to look awfully much like the SafeInit, but it will be some other API accessible only under control of the master interpreter.

For an example of a safe native code package, my very own e4Graph [L1 ] package has a SafeInit function that makes the package available in a safe interpreter and only does not make the "tgraph::open" function available. The reasoning is that "tgraph::open" would allow the safe interpreter to open new storages, use arbitrary on disk files, etc. Clearly a security violation. Instead, storages are explicitly shared with the slave safe interpreter by its master through "tgraph::transfer". The rest of the functionality *is* safe because the safe interpreter can not obtain access to storages that it wasn't given access to, only to storages that have explicitly been shared with it by its master. Yes, the safe slave interpreter could do arbitrary damage to the storages that the master chose to share, but that's a calculated risk that the master interpreter decided to take. I consider this risk not to be serious, on the same order as the risk taken by the master when "interp transfer"ing Tcl I/O channels into a slave safe interpreter. The end conclusion is that the safe slave interpreter is as safe with as it is without the provided functionality.

On the other hand, if you want to give a safe slave interpreter access to sockets, the risks are more serious. In that case we need to implement a way to protect resources outside of Tcl on the local machine from serious damage, ideally making them inaccessible to the untrusted code. So for that you could use the "outside" security policy that Laurent Demailly and I wrote for the Tcl plugin. This policy protects the local machine against programs running on other machines, but allows the interpreter to communicate with those programs by opening sockets on ports on those machines. The slave safe interpreter cannot open sockets on ports serviced by the local machine, so it cannot connect e.g. to your smtpd to send hate mail from your machine. But it can connect to nearly anything off of your machine. This is a calculated risk that the master interpreter chose to take: while it protects your local machine from damage, it does not protect your reputation from damage.

As another example, Expect should not have a SafeInit. That is because it provides commands like "spawn" which can be used to execute any command provided by the OS. If the SafeInit hid that command from the safe slave interpreter, perhaps it'd be OK, but "spawn" is so central to the functioning of Expect scripts that removing it makes the package nearly unusable.


Should add more about security policies and how to use them to extend safe slave interpreters. Maybe I'll even get motivated to extricate this functionality from the Tcl plug-in and make it useful on its own Jacob Levy