On Mon, 27 Feb 2023 at 02:32, python--- via Python-ideas <python-ideas@python.org> wrote:
Supply chain attacks are becoming a pressing concern in software development due to the large number of dependencies and multiple attack vectors. Using third party modules (libraries, packages etc) is always a risk but the true potential of these attacks is now being weaponized. One way to deal with the risk is by limiting access to sensitive APIs like filesystem, shell, network and ffi so that packages which aren't explicitly granted permissions cannot use them, reducing their ability to do damage.
For example, a yaml parser should not need to use ffi, network nor shell. A command line argument parser library should not use network, ffi nor filesystem. Deno, a runtime for Typescript contains an interesting implementation of a permissions model for APIs.
Okay, so, looking at this freshly now that I can actually review and run the code (thanks for pointing out that I was using the wrong comparison base). Here's a basic POC using the example from your readme: ---- policy.json ---- { "socket": ["requests"] } ---- restricted.py ---- # I should be restricted and not allowed to import socket try: import socket except ImportError as e: print("Importing of socket blocked:", e) import sys socket = sys.modules["socket"] print("Hey look, sockets!", socket.socket()) ---- runme.py ---- # import sockets # do you have this? # import requests # or this? import restricted This correctly errors out. So, now to demonstrate how easy this is to break. The first and most obvious form of breakage is that, if the requests module is EVER imported (or sockets directly, which can be done inside runme), the module will exist inside sys.modules and can be used from anywhere. (And if you break that, then all kinds of things will break, including identity checks of sentinel objects, exception hierarchies, etc. We NEED that imported module commonality.) But here's the thing: if you stop ANY other module from importing sockets, that means that your code will break any time anything in the standard library calls on it. So this is basically going to be good ONLY for small and tightly controlled projects where you know exactly what's importing what - and if you already know that, you don't really need a policy. In fact, if your system works, so would something that just blocks the entire *process* from using sockets, because there's actually no viable boundary here. In general, that's the way to sandbox Python code. Do it at the process level, not the module level. You're doomed to fail otherwise. ChrisA ChrisA