danthedeckie / simpleeval

Simple Safe Sandboxed Extensible Expression Evaluator for Python
Other
451 stars 85 forks source link

We should switch to explicitly giving permission for methods / data access #125

Open danthedeckie opened 1 year ago

danthedeckie commented 1 year ago

See discussion from #81

This would be a breaking change for anyone sending custom objects to the library.

We'd need a way to specify which things can or cannot be used by the library?

Something like

class MyThing:
    def foo(self):
        return 42

    def bar(self):
        exit(1)

s = SimpleEval()
# The new feature:
s.permit(MyThing, {'foo'})

# And test it:
s.names = {'thing', MyThing()}
s.eval('thing.foo()') # -> 42
s.eval('thing.bar()') # -> throws NotAllowedException

? Something like that?

KOLANICH commented 1 year ago

I think that even the most basic things that cannot be executed symbolically should require a permission at very granular level. Yes, getattr should also require a permission. Using getattr one can get a class, then a module, then the module imported into that module and so on. So the virtual machine should be isolated from the interpreter. No really imported modukes, only very basic computations. Any tradeoff here can result into sandbox bypass. Ones who want a tradeoff should either just use eval or make an own solution.

throws NotAllowedException

I'd prefer everything that is nkt explicitly allowed as being simple non-existent within the sandbox.

s.permit(MyThing, {'foo'})

I think that no objects from the program should be exposed to the sandbox. If a user wants to expose, he has to create the special proxy objects. That are not to be exposed directly, but through kinda a syscall. And that are exposed wholly. If a user doesn't want to expose a function, he doesn't define it within the object.

danthedeckie commented 1 year ago

That's a really interesting take on this, @KOLANICH .

I guess it's going to be a balance of ergonomics Vs making it really hard to accidentally expose things you don't want to.

100% agree on gettattr.

I wonder if it's possible using the same core to have multiple versions / layers? Like a literally "simple" eval which is only really for maths & string manipulation with names, kinda thing, and then a version which adds in objects access via proxies, then another w/o proxies but with very locked down access, and. Another which grants a bit more access, but is named "unsafe" somehow...

Still thinking out loud here.

A permit method could actually wrap any instances of that type of object in a proxy automatically, perhaps? Hmmmm