Fix (interpreter security): builtins functions passed as tools enable the use of compile, eval, exec (#274)

This commit is contained in:
tandiapa 2025-01-20 17:06:47 +01:00 committed by GitHub
parent 7a91123729
commit a4612c98dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 36 additions and 1 deletions

View File

@ -604,6 +604,8 @@ def evaluate_call(
# cap the number of lines # cap the number of lines
return None return None
else: # Assume it's a callable object else: # Assume it's a callable object
if (func in [eval, compile, exec]) and (func not in static_tools.values()):
raise InterpreterError(f"Invoking eval, compile or exec is not allowed ({func_name}).")
return func(*args, **kwargs) return func(*args, **kwargs)

View File

@ -916,4 +916,37 @@ shift_intervals
code = 'capitals = {"Czech Republic": "Prague", "Monaco": "Monaco", "Bhutan": "Thimphu"};capitals["Butan"]' code = 'capitals = {"Czech Republic": "Prague", "Monaco": "Monaco", "Bhutan": "Thimphu"};capitals["Butan"]'
with pytest.raises(Exception) as e: with pytest.raises(Exception) as e:
evaluate_python_code(code) evaluate_python_code(code)
assert "Maybe you meant one of these indexes instead" in str(e) and "['Bhutan']" in str(e).replace("\\", "") assert "Maybe you meant one of these indexes instead" in str(
e
) and "['Bhutan']" in str(e).replace("\\", "")
def test_dangerous_builtins_calls_are_blocked(self):
unsafe_code = "import os"
dangerous_code = f"""
exec = callable.__self__.exec
compile = callable.__self__.compile
exec(compile('{unsafe_code}', 'no filename', 'exec'))
"""
with pytest.raises(InterpreterError):
evaluate_python_code(unsafe_code, static_tools=BASE_PYTHON_TOOLS)
with pytest.raises(InterpreterError):
evaluate_python_code(dangerous_code, static_tools=BASE_PYTHON_TOOLS)
def test_dangerous_builtins_are_callable_if_explicitly_added(self):
dangerous_code = """
compile = callable.__self__.compile
eval = callable.__self__.eval
exec = callable.__self__.exec
eval("1 + 1")
exec(compile("1 + 1", "no filename", "exec"))
teval("1 + 1")
texec(tcompile("1 + 1", "no filename", "exec"))
"""
evaluate_python_code(
dangerous_code, static_tools={"tcompile": compile, "teval": eval, "texec": exec} | BASE_PYTHON_TOOLS
)