subprocess.run()比os.system()更安全,因为前者默认不调用shell、以列表形式传参,使分号等特殊字符被当作普通字符串处理,天然防御命令注入;后者则无条件交由shell解析,用户输入含;、&&或$()即可执行任意命令。

为什么 subprocess.run() 比 os.system() 更安全?
因为 os.system() 会把整个字符串交给 shell 解析,参数里混入 ;、&&、$() 就可能执行任意命令;而 subprocess.run() 默认不经过 shell,参数以列表形式传入,shell 特殊字符被当作普通字符串处理,天然防注入。
常见错误是写成 subprocess.run("ls -l /tmp", shell=True) —— 这等于自己打开漏洞。只要不用 shell=True,就基本避开最危险的路径。
- 必须把命令和参数拆成列表:
["ls", "-l", "/tmp"],不能拼接字符串 - 路径或文件名含空格时,列表方式仍能正确识别,字符串方式容易截断
- 如果真要 shell 功能(如管道
|、通配符*),才考虑shell=True,且必须严格校验输入
如何安全传入用户可控的参数?
用户输入(比如表单里的文件名、搜索关键词)绝不能直接拼进命令列表。应先做最小化清洗,再用 shlex.quote() 包裹——它会把 foo; rm -rf / 转成 'foo; rm -rf /',让 shell 当作一个参数字面量。
但注意:shlex.quote() 只在 shell=True 时有意义;如果不用 shell,就根本不需要 quote,直接塞进列表即可。
Python 3.14.2是Python编程语言在2025年12月5日发布的稳定版本,属于3.14系列的第二个维护更新。该版本包含了18项修复,重点解决了多进程、数据类及正则表达式等模块的回归问题,并修复了CVE-2025-12084等安全漏洞。此版本标志着自由线程模式(移除GIL)正式获得官方支持,是Python发展的重要里程碑。
- 不用 shell:直接
["grep", user_input, "/var/log/syslog"]—— 安全,无额外处理 - 必须用 shell(如需要重定向):
subprocess.run(f"grep {shlex.quote(user_input)} /var/log/syslog > result.txt", shell=True) - 避免对整条命令 quote,只 quote每个动态参数,否则可能破坏语法
capture_output=True 和 text=True 怎么配?
想拿到命令输出又不想手动 decode,必须同时设 capture_output=True 和 text=True。漏掉 text=True,result.stdout 是 bytes 类型,后续字符串操作会报 TypeError。
另外,check=True 很关键:它让异常自动抛出,避免忽略非零退出码(比如 grep 没匹配到内容时返回 1,不代表失败,但有些命令返回 1 真是出错了)。
- 推荐组合:
subprocess.run(cmd, capture_output=True, text=True, check=False),然后自己判断result.returncode - 如果确定命令不该失败(如
cp复制成功),用check=True让异常暴露问题 -
stderr=subprocess.STDOUT可合并错误流,方便统一捕获日志
PATH 和工作目录怎么控制?
不要依赖系统默认 PATH,尤其在服务端运行时,环境变量可能被精简。显式指定 executable 或用绝对路径调用二进制(如 /bin/ls),避免因 PATH 不一致导致命令找不到。
当前工作目录也影响相对路径行为,比如用户传入 "./data/file.txt",应在可信目录里 cwd= 切换过去,而不是在脚本所在目录执行。
- 指定路径:
subprocess.run(["/usr/bin/find", "/home", "-name", "config.ini"], cwd="/") - 限制权限:提前用
os.chdir()切到沙箱目录,再调subprocess.run(..., cwd="sandbox/") - 避免传
env=os.environ,应构造最小化env字典,删掉敏感变量如LD_PRELOAD
cwd 是用户可写的目录,且命令本身有漏洞(比如旧版 git 对 .git/config 的解析缺陷),仍可能被利用。安全不是单点防御,而是层层收敛输入来源、执行环境和权限边界。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










