[Python-Dev] Capabilities

Jeremy Hylton jeremy@zope.com
10 Mar 2003 12:36:22 -0500

On Mon, 2003-03-10 at 05:51, Ka-Ping Yee wrote:
> It seems to me that the "rexec vs. proxy" debate is really about
> a very different question: How do we get from Python's currently
> promiscuous objects to properly restricted objects?

I think that's the right question.

> (Once we have properly restricted objects in either fashion, yes,
> definitely, using proxies to restrict access is a great technique.)
> If i understand correctly, the "proxy" answer is "we create a
> special wrapper object, then the programmer has to individually
> wrap any object they want to be secure".  And the "rexec" answer
> is "we create an interpreter mode in which all objects are secure".

The proxy answer is a bit more complex.  Any object returned from a
proxy is itself wrapped in a proxy, except for immutable objects like
None, ints, and strings.  The initial proxy creates a barrier between
the code that created the proxy and the client that uses the proxy.

> I think the latter is far better.  To have any sort of real chance
> at establishing security, you have to start from a place where
> everything is secure, instead of starting from a place where
> everything is insecure and you have to individually secure every
> single object with its own wrapper.

It would indeed be impractical to wrap every object manually.  I think
both approaches tend towards the design principle of fail-safe defaults
and complete mediation.  A proxy mediates all access to the object it
wraps.  By default, it allows no access.  When it allows access, it
creates new proxies that provide the same facilities as the original. 
The one exception is for immutable objects.  (Immutability is good for
so many reasons.)

> The eventual ideal is to have a system where all objects are
> "pure" objects (i.e. non-introspectable capabilities) by default.
> Anyone wanting to do introspection would simply have to obtain
> the "introspect" capability from a privileged place (e.g. sys).
> For example,
>     class Foo:
>         pass
>     print Foo.__dict__                  # fails
>     from sys import introspect
>     print introspect(Foo).__dict__      # succeeds
> When running the interpreter in secure mode, "introspect"
> would just be missing from the sys module (again, ideally
> sys.introspect wouldn't exist by default, and a command-line
> option would turn it on, but i realize that's far away).
> This would have the effect of the "introspectable flag" that
> Guido mentioned, but without expending any storage at all,
> until you actually needed to introspect something.

If Python's introspection were less ad hoc, I suppose this issue would
be easier to tackle.  (Has anyone done security design for a CLOS-style
meta-object protocol?)

Note that the biggest problem with the introspectable flag is that it
would need to be checked all over the interpreter internals.  For
example, the interpreter optimisizes bound method calls by extracting
the im_self and im_func and calling im_func directly passing im_self and
the rest of the arguments.  This is all done within the mainloop using a
single type check and a bunch of macros to extract fields from the bound
method.  It is pretty common to use macros that depend on the
representation of builtin types like functions, methods, dictionaries,