Open hobovsky opened 3 years ago
Copy/pasted from one of the preloaded:
PURPOSE:
This code blocks all attempts to import one of the targeted modules, in any of the
following ways manners (here, for numpy):
import numpy
__import__("numpy")
import numpy.linalg
from numpy import array
Calling the import function from globals, locals or even __builtins__ are blocked
the very same way since they all refer to the very same function.
USAGE:
Update the extension of the list 'toForbid', at the end of the preloaded part with
the names of the modules you wanna forbid.
WARNING:
* Some packages, when imported, have dependencies that can contain one or many
modules that are forbidden.
The typical problem is that 'random' cannot be imported anymore if 'os' or 'sys'
are forbidden. Numpy needs 'sys' too, for example, and so on...
That leads to another problem: you may forbid some legit imports too.
See "SUBSEQUENT IMPORTS" and "AUTHORIZING USER IMPORTS" sections to handle
those problems.
* If you wanna forbid the 're' module, you'll have to add its name after the 'sys'
module at this line:
for name in modulesToKeep + ('sys', 're'):
...
Otherwise the user will have access to it (because it's used in the module_forbidder)
EFFICIENCY REQUIREMENTS:
- To make it useful, some modules have to be forbidden by default. They are listed
in the first declaration of the tuple 'toForbid', (see lower).
- To forbid retro-engineering of the module_forbidder, it's reference in the global
scope is deleted.
Note that the 'inspect' module isn't reachable anymore because its import relies
on some of the modules forbiden by default (like os and/or sys)
- Finally, open, exec and eval functions are "Nonified" to forbid some other ways to
cheat.
Though, that makes further imports completely impossible after the forbidder
has been setup: see the "SUBSEQUENT IMPORTS" part, about the import needed in the
test cases part.
SUBSEQUENT IMPORTS: (importing modules for the test suite)
Because of the requirements to keep the forbidder working, imports from the test suite aren't
possible anymore. To get those modules in there, without letting to the user the possiblity to
mess with them, you have to go through the "extract" process:
1. In the 'module_forbidder' function, import all the module you need. To do so, use the
'modulesToKeep' tuple, putting in there the names of the modules as strings.
The imports are scope specific, and since the sys, gc or whatever modules aren't accesible
anymore, the user cannot have acces to them.
Those module names will automatically be added to the restricted names (because even if the
imports are scope dependent the user could have acces to them trying a regular import, since
python imports only one single time a module (unless 'importlib.reload' or equivalent is used)
and the user would actually only create a new alias for the alredy stored module).
2. Define the 'checker' variable, as "extract.(some random char sequence here)" to be able to
access the modules you loaded before.
Note: the char sequence has to be consistent with the syntaxe of the imports => like r'\w+'
3. from the test suite, get back the different modules with the "extract" fake import and then
do your stuff with them.
Example: - In the module forbidder:
checker = 'extract._HjsloidfgskhS543668DGHZ'
modulesToKeep = ('random',)
- Then in the test suite:
(random,) = __import__('extract._HjsloidfgskhS543668DGHZ')
randint = random.randint
Reminder: Do NEVER import random right from the preloaded (root) part, unless you're ok with a
user messing with its seed... x)
AUTHORIZING USER IMPORTS: (== "don't make the user hate you"... x) )
If you have to allow for the user some modules that have dependencies on forbidden modules, you
just have to make those imports yourself at the beginning of the preloaded part.
Just do themin their simplest form, like 'import numpy', and it will handle any aliasing the
user could use (like 'import numpy as np').
Note: the classic modules still can be imported the usual way by the user:
heapq, itertools, collections, functools, operator, re, ...
COMPATIBILITY NOTES:
Warning if higher versions are available: 3.6.4, for example, needs the following change:
globals()['__builtins__'].__import__ =...
instead of:
__builtins__['__import__'] = ...
STRATEGY NOTE (archive):
A first verison was using a "switch", to activate/deactivate the import forbider, so that the author
can import stuff in the test suite (which is loaded after the code of the user), but since the addition
of the resetting of the open and exec functions, some modules (most of them...) cannot be imported
anymore, even if the original import function is used.
That leads to te use of the "extract" fake import.
it's not up to date...
the thing about the pwd to get the random module back in the tests doesn't work properly (if not at all...)
the thing about the pwd to get the random module back in the tests doesn't work properly
Can you please elaborate?
A snippet with module forbidder.