我想将功能性存根附加到我编写的数据处理作业中,并且能够通过配置文件应用这些存根会很方便。
我可以通过eval
函数来加载和运行这些函数,但是希望能够控制所评估函数可以在其中运行的可用名称空间“沙盒”,因此可以避免恶意代码注入。
在python文档中,建议先屏蔽__builtins__
,然后将全局变量和局部变量中的任意一个(或者是两者都不清楚?)填充为包含执行名称空间中对象的字典。
执行此操作时,我一直成功运行的代码停止工作。
我认为这是因为我的测试lambda之一是引用通常从datetime
模块导入的函数-但我不清楚如何使它们成功附加到命名空间。
from datetime import datetime
now = datetime.now()
lambdas = { "Report Date" : "lambda x : now.strftime(\"%d/%m/%Y\")",
"Scary Test" : "lambda x : os.curdir " }
compiled_funcs = {k:eval(v) for k,v in lambdas.items()}
compiled_funcs ['Report Date'](1)
>>> '15/04/2019'
compiled_funcs ['Scary Test'](1)
>>> '.'
现在,我想编辑eval()
函数以限制可用范围,以便datetime函数继续运行,但是os
模块失败(如果我可以调用os命令,那么我可能会做一些可怕的事情,例如擦拭磁盘,或更糟)
我尝试过以下构造:
compiled_funcs = {k:eval(v,{'__builtins__':None, "now" : now, "datetime" : datetime, } , { }) for k,v in lambdas.items()}
但是当我这样做时,出现以下错误:
AttributeError: 'NoneType' object has no attribute '__import__'
这暗示我想在某处/以某种方式应用的功能试图在行中调用/导入某些内容-并且(大概)由于使__builtins__
内容令人厌烦而被正确阻止。有没有办法将这些功能预先打包并注入到eval全局变量或局部变量字典中,以启用一组预定义的功能工具?
完成这项工作后,我应该可以对其进行扩展,以便整理自己的安全函数调用子集,以暴露给配置文件中的运行时集合。
我在上面知道,我可以不带参数定义lambdæ-但在我的实际代码中,馈入单个参数是正常的,因此已相应地构建了测试代码。