避免命令注入的关键是禁用 shell=true 并使用列表传参,严格校验输入;必要时用 shlex.quote() 转义或白名单过滤;优先采用标准库替代系统命令,并辅以最小权限与环境隔离。

避免 Python 中的命令注入,关键在于不把用户输入直接拼接到 shell 命令字符串里调用 subprocess。只要绕过 shell 解析、使用参数列表形式调用,并严格校验输入,就能基本杜绝此类风险。
永远用 list 形式传参,禁用 shell=True
这是最核心的安全原则。当调用 subprocess.run()、subprocess.Popen() 等函数时,把命令和参数写成 Python 列表,而不是拼接字符串:
- ✅ 安全写法:
subprocess.run(["ls", "-l", "/home/user"]) - ❌ 危险写法:
subprocess.run(f"ls -l {path}", shell=True)(用户控制path时可注入; rm -rf /)
使用列表时,Python 会绕过 shell,直接执行程序,参数不会被 shell 解释,通配符、重定向、管道符等都失效——这反而是好事,因为消除了注入面。
若必须用 shell 功能,先白名单过滤再转义
极少数场景(如需要管道、变量展开)不得不启用 shell=True,此时绝不能拼接原始输入。应:
立即学习“Python免费学习笔记(深入)”;
- 对输入做严格白名单校验(例如只允许字母、数字、下划线、指定路径前缀)
- 或使用
shlex.quote()对每个待插入的参数单独转义 - 避免在 shell 字符串中混入未处理的用户数据
示例:import shlex; cmd = f"grep {shlex.quote(pattern)} {shlex.quote(logfile)}" —— 这能安全处理含空格、引号、$ 的输入。
优先考虑替代方案,绕过系统命令
很多本该用 shell 命令完成的任务,在 Python 标准库中已有更安全、更可控的实现:
- 文件操作:用
os.listdir()、pathlib.Path.glob()替代ls - 进程管理:用
psutil获取进程信息,而非解析ps输出 - 压缩/解压:用
zipfile、tarfile替代unzip或tar - 网络诊断:用
socket或requests测试连通性,而非调用ping
这些方式不依赖外部程序,无注入风险,且跨平台兼容性更好。
最小权限 + 环境隔离
即使代码逻辑安全,运行环境也需加固:
- 以低权限用户运行 Python 进程(避免用 root 执行含用户输入的 subprocess)
- 在容器或沙箱中运行可疑命令(如用户上传脚本触发的调用)
- 限制子进程可访问的路径(通过
cwd参数或 chroot) - 设置超时(
timeout=)防止恶意命令长期占用资源
这些不是替代代码层防护,而是纵深防御的必要补充。










