如何安全运行别人上传的Python代码?
在日常开发里啊,最让人头疼的一类需求就是——别人上传了一段 Python 代码让你跑,这种场景不少见,比如在线判题系统、数据分析平台,甚至团队里做 demo 的时候也会遇到。但问题也来了:你敢直接 exec 吗?十有八九就变成“帮别人挖坑自己跳”了。下面就聊聊几个比较靠谱的思路。
为什么不能直接跑?
想象下,有人上传这么一段代码:
import os
os.remove("/etc/passwd")
如果你在服务器上直接跑,数据就废了。更糟糕的是,它还能开网络连接、疯狂占 CPU 内存,甚至 fork 炸掉你的机器。所以第一条原则:永远不要直接运行。
用沙盒隔离
最常见的方法就是搞个沙盒环境。比如用 Docker 容器 或 虚拟机,把上传的代码限制在一个“盒子”里跑,出了问题也不会伤到宿主机。
简单示例(假设你用 Python 调用 Docker):
import dockerclient = docker.from_env()
container = client.containers.run(
"python:3.9",
"python -c 'print(1+1)'",
detach=True,
network_disabled=True,
mem_limit="128m",
cpu_quota=50000
)
print(container.logs().decode())
这里做了几件事:禁用网络、限制内存 128M、限制 CPU,保证代码不会乱跑。
控制可用的模块
就算在沙盒里,也要限制能用的库。不然有人上传 subprocess.Popen("rm -rf /"),一样危险。可以通过在执行环境里只保留安全的内置函数,比如这样:
safe_globals = {"__builtins__": {"print": print, "range": range}}
code = "for i in range(5): print(i)"
exec(code, safe_globals)
这里我们手动指定了能用的函数,其他的比如 open、os 就访问不到了。
超时和资源控制
除了 Docker 这种“硬隔离”,你也可以在本地用 资源限制。Linux 下有个 resource 模块,可以限制 CPU 时间、内存使用,比如:
import resource, signaldeflimit_resources():
resource.setrlimit(resource.RLIMIT_CPU, (1, 1)) # 最多 1 秒 CPU
resource.setrlimit(resource.RLIMIT_AS, (100*1024*1024, 100*1024*1024)) # 100MB 内存
defhandler(signum, frame):
raise TimeoutError("Time limit exceeded")
signal.signal(signal.SIGXCPU, handler)
limit_resources()
exec("while True: pass") # 会被强制杀掉
这样就算有人写死循环,也撑不了多久。
更高级的玩法
如果你做的是对外服务,最好是多层防护:
容器隔离(Docker/K8s) 系统层 cgroup 限制(CPU/内存/文件数) 语言层安全沙盒(过滤内置函数) 超时机制(防死循环)
这几层叠加起来,基本就能保证别人上传的代码不会把你的服务拖垮。
总之,安全运行别人的 Python 代码,其实就是“不给它机会捣乱”。容器是最通用的方案,配合 Python 自带的 resource、信号超时、白名单函数,就能做到可控可用。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html
虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB,点击下方公众号回复关键字 python 全部免费领