0

I am trying to execute javascript code in python, using pyv8 safely. At the end of the day, I have an object being used by javascript, with few fields I would like to have hidden.

I know python doesn't have encapsulation (as explained in this question), but yet, is there a way to disable access using __getattribute__?

class Context(object):
    def __init__(self, debug):
        self._a = ...
        self._b = ...
        self._c = ...
        self._unlocked = False

    def __enter__(self):
        self._unlocked = True

    def __exit__(self, exc_type, exc_val, exc_tb):
        self._unlocked = False

    def __getattribute__(self, name):
        if object.__getattribute__(self, "_unlocked"):
            return object.__getattribute__(self, name)

        if name.startswith("_"):
            return None

        return object.__getattribute__(self, name)

So this object denies access to a "private" variables, unless unlocked using like this:

ctx = Context()
...
with ctx:
   # _b is accessible here
   print ctx._b 

As far as there's no way to do with from javascript, nor to call __enter__ since the object is "locked".

Seems not very efficient though. Is there a better way?

Community
  • 1
  • 1
desertkun
  • 1,027
  • 10
  • 19
  • 1
    Name mangling performed by two leading underscores will cover all valid use cases of 'private variables' in python. – Natecat Jan 26 '17 at 00:12
  • Note that variables like `__foo` will be mangled so they're not easily visible to code outside the class that contains them (although you can get around it). the `__` is more of a "stay away even if you're not technically prevented from doing so". – mmenschig Jan 26 '17 at 00:15
  • Yes, '__a' is actually available as '_A__a' by compiler. What I want is to literally disable any way to get the value. – desertkun Jan 26 '17 at 00:25
  • Please tell me you're not doing this in an attempt to sandbox the JS so you can run untrusted code... – Sean McSomething Jan 26 '17 at 00:30
  • @SeanMcSomething well, kinda. I want sandbox javascript code, not python. Is there a way to access object's attributes, if object denies so via `__getattribute__`? That's why I try to use `with`. Please explain why it's bad and why it won't work. – desertkun Jan 26 '17 at 11:20
  • @desertkun - once the JS is able to call into your Python arbitrarily, you've already lost the game. Python's a highly dynamic language & any sort of security restrictions like that should be enforced at the level of the JS interpreter itself - probably by giving it a whitelist of objects it's allowed to access and not putting any sensitive data inside of them. – Sean McSomething Jan 27 '17 at 18:30
  • @SeanMcSomething Could you please elaborate this https://github.com/buffer/pyv8/pull/2 ? If you familiar with `V8`, I've patched it so it returns `null` for every `python` object starting with `_`. – desertkun Jan 29 '17 at 20:36

1 Answers1

0

You could use a property getter that restricts access?

class Context(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
    """I'm the 'x' property."""
        return "Property can not be accessed."

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x

More info can be found here: https://docs.python.org/3/library/functions.html#property

mmenschig
  • 1,088
  • 14
  • 22
  • 1
    The thing is that this doesn't prevent a user from accessing `foo._x`. – cadolphs Jan 26 '17 at 00:23
  • 1
    If the user has a reference to `foo`, she can get to any of `foo`'s data. This is why python no longer pretends to have a sandboxed execution mode. What you're asking for isn't possible in Python. – cco Jan 26 '17 at 01:51