[Python-Dev] Capabilities (we already got one)

Phillip J. Eby pje@telecommunity.com
Tue, 01 Apr 2003 13:01:54 -0500


 >However, you don't use the same technique to control access to Python 
*modules*
 >such as the zipfile module, because the "import zipfile" statement will 
give the
 >current scope access to the zipfile module even if nobody has granted such
 >access to the current scope.
 >...
 >So your solution to this, to prevent code from grabbing privileges willy 
nilly
 >via "import" and builtins, is rexec, which creates a scope in which code
 >executes (now called a "workspace"), and allows you to control which 
builtins
 >and modules are available for code executing in that "workspace".

Almost.  I think you may be confusing module *code* and module 
*objects*.  Guido pointed this out earlier.

A Python module object is populated by executing a body of *code* against 
the module *object* dictionary.  The module object dictionary contains a 
'__builtins__' entry that gives it its "base" capabilities.

Module *objects* possess capabilities, which are in their dictionary or 
reachable from it.  *Code* doesn't possess capabilities except to constants 
used in the code.  So access to *code* only grants you capabilities to the 
code and its constants.

So, in order to provide a capability-safe environment, you need only 
provide a custom __import__ which uses a different 'sys.modules' that is 
specific to that environment.  At that point, a "workspace" consists of an 
object graph rooted in the supplied '__builtins__', locals(), globals(), 
and initially executing code.

We can then see that the standard Python environment is in fact a 
capability system, wherein everything is reachable from everything else.

The "holes" in this capability system, then, are:

1. introspective abilities that allow "breaking out" of the workspace (such 
as the ability to 'sys._getframe()' or examine tracebacks to "reach up" to 
higher-level stack frames)

2. the structuring of the library in ways that equate creating an instance 
of a class with an "unsafe" capability.  (E.g., creating instances of 
'file()') coupled with instance->class introspection

3. Lack of true "privacy" for objects.  (Proxies are a useful way to 
address this issue, because they allow more than one "capability" to exist 
for the same object.)