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, etc.