我正在 Python 中寻找一种安全机制来执行来自用户的潜在不安全脚本代码。
代码示例:
def public(v):
print('Allowed to trigger this with '+v)
def secret():
print('Not allowed to trigger this')
unsafe_user_code = '''
def user_function(a):
if 'o' in a:
public('parameter')
a = 'hello'
user_function(a)
'''
run_code(unsafe_user_code, allowed=['public'])
这可以通过
exec()
轻松实现,但据我了解,在 Python 中无法安全地使用 exec()
。
这是我的要求:
public()
)到目前为止我发现的唯一方法是使用解析库,我必须自己定义所有内容(例如这个:https://github.com/lark-parser/lark)。
有没有更好的方法来实现这样的目标?
谢谢!
如果您想复制,这里是完整的 python 文件:
def run_code(code_to_run: str, context: dict):
code = compile(code_to_run, "", "exec")
exec(code, context)
return
具有以下用法:
variables = {"variable_a": "A", "variable_b": "B", "variable_c": "C"}
run_code(
"""
# We can work with the variables here
all_variables = [variable_a, variable_b, variable_c]
joined = ",".join(all_variables)
print("Joined:", joined)
combined = variable_a + variable_b + variable_c
print("Combined:", combined)
""",
variables,
)
它会打印到终端:
Joined: A,B,C
Combined: ABC
我认为你不需要解析库。 您可以使用 python 的内置函数之一,称为 compile()。
你可以这样编译代码:
text_to_compile = "print('hello world')"
code = compile(
text_to_compile, # text to compile
'file_name', # file name
'exec' # compile mode
)
然后使用内置的 exec 函数运行它:
exec(code) # prints 'hello world' in the terminal
如果您想限制其对变量的访问,您可以定义其
globals
和 locals
并作为第二个和第三个参数传递:
global_variables = { "cool":"cool value" }
local_variables = {"more_cool": "cool value"}
exec(
code,
global_variables,
local_variables
)
如果你给它这个代码:
print("GLOBALS:", list(globals().keys()))
print("LOCALS:", list(locals().keys()))
print("cool:", cool)
print("more_cool:", more_cool)
它输出:
GLOBALS: ['cool', '__builtins__']
LOCALS: ['more_cool']
cool: cool value
more_cool: cool value