Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preventing Python code from importing certain modules?

People also ask

Why is Python running a module when I import it?

Because this is just how Python works - keywords such as class and def are not declarations. Instead, they are real live statements which are executed. If they were not executed your module would be empty.

Which of the following do we use to prevent code from being run when the module is imported?

We can use an if __name__ == "__main__" block to allow or prevent parts of code from being run when the modules are imported.


If you put None in sys.modules for a module name, in won't be importable...

>>> import sys
>>> import os
>>> del os
>>> sys.modules['os']=None
>>> import os
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named os
>>>

Have you checked the python.org article on SandboxedPython, and the linked article?

Both of those pages have links to other resources.

Specifically, PyPi's RestrictedPython lets you define exactly what is available, and has a few 'safe' defaults to choose from.


8 years, yeesh, and nobody has figured this one out? :/

You can override the import statement or aka the __import__ function.

This is just a tested scribble-code because I couldn't find any legit reference:

import importlib

def secure_importer(name, globals=None, locals=None, fromlist=(), level=0):

    if name != 'C': print(name, fromlist, level)

    # not exactly a good verification layer
    frommodule = globals['__name__'] if globals else None
    if name == 'B' and frommodule != 'C':
        raise ImportError("module '%s' is restricted."%name)

    return importlib.__import__(name, globals, locals, fromlist, level)

__builtins__.__dict__['__import__'] = secure_importer

import C

and here's the tests for that code:

Python 3.4.3 |Anaconda 2.3.0 (32-bit)| (default, Mar  6 2015, 12:08:17) [MSC v.1600 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>> 
B ('f',) 0
imported secure module
>>> from B import f
B ('f',) 0
linecache None 0
encodings.utf_8 ['*'] 0
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    from B import f
  File "\home\tcll\Projects\python\test\restricted imports\main.py", line 11, in secure_importer
    raise ImportError("module '%s' is restricted."%name)
ImportError: module 'B' is restricted.
>>> import C
>>> 

Please do not comment about me using Python34, I have my reasons, and it's my primary interpreter on Linux specifically for testing things (like the above code) for my primary project.


Google App Engine's open source SDK has a detailed and solid implementation of mechanics to stop the importing of unwanted modules (to help detect code trying to import modules that aren't made available in the production instances of App Engine), though even that could be subverted if the user code was evil rather than just mistaken (production instances obviously have more layers of defense, such as simply not having those modules around at all;-).

So it all depends on how in-depth your defense needs to be. At one extreme you just stash the builtin __import__ somewhere else and replace it with your function that does all the checks you want before delegating to the __builtin__; that's maybe 20 lines of code, 30 minutes to implement and test thoroughly... but it might not protect you for long if somebody credibly offered me a million bucks to break into your system (and, hypothetically, I wasn't the goody-two-shoes kind of guy I actually AM, of course;-). At the other extreme you deploy an in-depth series of layers of defense that might take thousands of lines and weeks of implementation and testing work -- given that kind of resource budget I could surely implement something I would be unable to penetrate (but there's always the risk that somebody ELSE is smarter and more Python-savvy than I am, of course!).

So, how deep do you want to go, or rather, how deep can you AFFORD to go...?