[Python-Dev] Security capabilities in Python

Ka-Ping Yee python-dev at zesty.ca
Sat Apr 9 07:13:40 CEST 2005

On Fri, 8 Apr 2005, Eyal Lotem wrote:
> I would like to experiment with security based on Python references as
> security capabilities.

This is an interesting and worthwhile thought.  Several people
(including myself) have talked about the possibility of doing
this in the past.  I believe the two problems you mention can be
addressed without modifying the Python core.

> * There is no way to create secure proxies because there are no
> private attributes.

Attributes are not private, but local variables are.  If you use
lexical scoping to restrict variable access (as one would in
Scheme, E, etc.) you can create secure proxies.  See below.

> * Lots of Python objects are reachable unnecessarily breaking the
> principle of least privelege (i.e: object.__subclasses__() etc.)

True.  However, Python's restricted execution mode prevents access
to these attributes, allowing you to enforce encapsulation.  (At
least, that is part of the intent of restricted execution mode,
though currently we do not make official guarantees about it.)
Replacing __builtins__ activates restricted execution mode.

Here is a simple facet function.

    def facet(target, allowed_attrs):
        class Facet:
            def __repr__(self):
                return '<Facet %r on %r>' % (allowed_attrs, target)
            def __getattr__(self, name):
                if name in allowed_attrs:
                    return getattr(target, name)
                raise NameError(name)
        return Facet()

    def restrict():
        global __builtins__
        __builtins__ = __builtins__.__dict__.copy()

    # Here's an example.

    list = [1, 2, 3]
    immutable_facet = facet(list, ['__getitem__', '__len__', '__iter__'])

    # Here's another example.

    class Counter:
        def __init__(self):
            self.n = 0

        def increment(self):
            self.n += 1

        def value(self):
            return self.n

    counter = Counter()
    readonly_facet = facet(counter, ['value'])

If i've done this correctly, it should be impossible to alter the
contents of the list or the counter, given only the immutable_facet
or the readonly_facet, after restrict() has been called.

(Try it out and let me know if you can poke holes in it...)

The upshot of all this is that i think you can do secure programming
in Python if you just use a different style.  Unfortunately, this
style is incompatible with the way classes are usually written in
Python, which means you can't safely use much of the standard library,
but i believe the language itself is not fatally flawed.

-- ?!ng

More information about the Python-Dev mailing list