@@ -2,9 +2,53 @@ The available methods and variables used in ``exec()`` may introduce a security
2
2
You can restrict the use of these variables and methods by passing optional globals
3
3
and locals parameters (dictionaries) to the ``exec() `` method.
4
4
5
- However, use of ``exec `` is still insecure. For example, consider the following call
6
- that writes a file to the user's system:
5
+ However, use of ``exec() `` is still insecure if you allow some functions like
6
+ ``__import__ `` or ``open ``. For example, consider the following call that writes a
7
+ file to the user's system and then execute code unrestrained by the ``allowed_globals ``,
8
+ or ``allowed_locals `` parameters:
7
9
8
10
.. code-block :: python
9
11
10
- exec (""" \n with open("file.txt", "w", encoding="utf-8") as file:\n file.write("# code as nefarious as imaginable")\n """ )
12
+ import textwrap
13
+
14
+
15
+ def forbid_print (* args ):
16
+ raise ValueError (" This is raised when a print is used" )
17
+
18
+
19
+ allowed_globals = {
20
+ " __builtins__" : {
21
+ " __import__" : __builtins__ .__import__,
22
+ " open" : __builtins__ .open,
23
+ " print" : forbid_print,
24
+ }
25
+ }
26
+
27
+ exec (
28
+ textwrap.dedent(
29
+ """
30
+ import textwrap
31
+
32
+ with open("nefarious.py", "w") as f:
33
+ f.write(textwrap.dedent('''
34
+ def connive():
35
+ print("Here's some code as nefarious as imaginable")
36
+ '''))
37
+
38
+ import nefarious
39
+
40
+ nefarious.connive() # This will NOT raise a ValueError
41
+ """
42
+ ),
43
+ allowed_globals,
44
+ )
45
+
46
+
47
+ The import is used only for readability of the example in this case but it could
48
+ import a dangerous functions:
49
+
50
+ - ``subprocess.run('echo "print(\"Hello, World!\")" > nefarious.py' ``
51
+ - ``pathlib.Path("nefarious.py").write_file("print(\"Hello, World!\")") ``
52
+ - ``os.system('echo "print(\"Hello, World!\")" > nefarious.py') ``
53
+ - ``logging.basicConfig(filename='nefarious.py'); logging.error('print("Hello, World!")') ``
54
+ - etc.
0 commit comments