zopefoundation / RestrictedPython

A restricted execution environment for Python to run untrusted code.
http://restrictedpython.readthedocs.io/
Other
470 stars 38 forks source link

Can I restrict a number of defined packages and allow others? #185

Closed Ryan-Gordon1 closed 4 years ago

Ryan-Gordon1 commented 4 years ago

While using RestrictedPython a use case I would like to have is not allow the import of certain packages but allow others. For example I want to allow json but disallow requests. Is this currently possible by modifying safe_builtins or safe_utilities?

d-maurer commented 4 years ago

Ryan Gordon wrote at 2019-11-14 06:45 -0800:

While using RestrictedPython a use case I would like to have is not allow the import of certain packages but allow others. For example I want to allow json but disallow requests. Is this currently possible by modifying safe_builtins or safe_utilities?

RestrictedPython delegates such decisions to an external policy package.

I am using RestrictedPython in the context of Zope. Zope's policy package is AccessControl. AccessControl implements the policy "import forbidden unless explicitly allowed". To allow the import of a module, it has a function allow_module (and various other allow_* for other kinds of objects).

Summary: you can configure RestrictedPython to do what you want. Either use AccessControl directly or design your own policy package using AccessControl as some form of blueprint.

Ryan-Gordon1 commented 4 years ago

This was very helpful @d-maurer thank you for your comment. I have started to use AccessControl directly and can now achieve was asking. Would it be helpful if I did a write up on this ?

I have another question which I can file as a separate issue if thats better. I can now explicitly allow a module using AccessControl, I can also mark modules as private with the same package. My curious question now is if its possible to allow the importation of a module/package but disallow the importation of a certain module within that package. For example: We see the os package which has a number of modules within it. Is it possible to allow one module from within the package and restrict another ? Maybe allowing os.st and disallowing others.

d-maurer commented 4 years ago

Ryan Gordon wrote at 2019-11-20 01:19 -0800:

... My curious question now is if its possible to allow the importation of a module/package but disallow the importation of a certain module within that package.

If you allow the import of a package, you allow only its import, not that of contained modules/subpackages. You must use allow_module for contained modules/subpackages to allow their import. Usually, the imported module content has further usage restrictions (e.g. you would use ModuleSecurityInfo/ClassSecurityInfo/allow_class etc. to control the use of the module content).

I believe (event though I have not checked) that a allow_module("os.path") allows the import of "os.path", but not that of "os".

I avoid potentially tricky questions like this by providing a collection module (or several ones) which uses unrestricted Python to provide access to everything which should be available to restricted Python and then allow_module this module. This allows to precisely control which is availabe to restricted Python without very deep knowledge about internals.

Ryan-Gordon1 commented 4 years ago

If you allow the import of a package, you allow only its import, not that of contained modules/subpackages.

This was my expectation also and it works with a direct import

If I allow_module('os') I cannot import os.path If I allow_module('os.path') I can import os.path

But something I noticed is that if I allow_module(os) I am not able to import os.path but I am able to import it from the package like this from os import path

I avoid potentially tricky questions like this by providing a collection module (or several ones) which uses unrestricted Python to provide access to everything which should be available to restricted Python and then allow_module this module.

I will review this as an approach to solve this. Thank you for the guidance on this issue!

gotcha commented 4 years ago

@Ryan-Gordon1 Can this issue be closed ?

Ryan-Gordon1 commented 4 years ago

Yes, I can now restrict a number of packages and allow others through RestrictedPython. So we can close this. Would be good to keep a note of this comment:

But something I noticed is that if I allow_module(os) I am not able to import os.path but I am able to import it from the package like this from os import path

d-maurer commented 4 years ago

Ryan Gordon wrote at 2019-11-20 02:27 -0800:

... But something I noticed is that if I allow_module(os) I am not able to import os.path but I am able to import it from the package like this from os import path

This could be a bug or something normal.

If you have a package/module "M" and an attribute "A" in "M", then from M import A only involves importing "M".

Thus, if importing os imports os.path as a side effect and makes path available as attribute, your observed behaviour is to be expected. I just checked, that (at least under Python 2), this is indeed the case.

The approach below depends on this behaviour: whatever becomes an attribute ("A") of an imported module "M", can be accessed later via from M import A.

I avoid potentially tricky questions like this by providing a collection module (or several ones) which uses unrestricted Python to provide access to everything which should be available to restricted Python and then allow_module this module. I will review this as an approach to solve this. Thank you for the guidance on this issue!

Ryan-Gordon1 commented 4 years ago

Thus, if importing os imports os.path as a side effect and makes path available as attribute, your observed behaviour is to be expected. I just checked, that (at least under Python 2), this is indeed the case.

Thank you for investigating this @d-maurer and confirming that (on Python2) it is expected.