diff --git a/src/smolagents/local_python_executor.py b/src/smolagents/local_python_executor.py index 1b47d28..effb488 100644 --- a/src/smolagents/local_python_executor.py +++ b/src/smolagents/local_python_executor.py @@ -604,6 +604,8 @@ def evaluate_call( # cap the number of lines return None 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) diff --git a/tests/test_python_interpreter.py b/tests/test_python_interpreter.py index 9fcd218..4e368da 100644 --- a/tests/test_python_interpreter.py +++ b/tests/test_python_interpreter.py @@ -916,4 +916,37 @@ shift_intervals code = 'capitals = {"Czech Republic": "Prague", "Monaco": "Monaco", "Bhutan": "Thimphu"};capitals["Butan"]' with pytest.raises(Exception) as e: 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 + )