必须替换yaml.load(),否则存在任意代码执行风险;pyyaml 5.1+默认禁用不安全解析器,yaml.load()底层仍调用fullloader,可能执行!!python/object等恶意标签,应统一改用yaml.safe_load()。

必须替换 yaml.load(),否则存在任意代码执行风险。这个警告不是提醒你“可以忽略”,而是明确告诉你:当前用法等同于执行不受控的 Python 代码。
为什么 yaml.load() 会触发 YAMLLoadWarning
PyYAML 5.1+ 默认禁用了不安全的解析器,yaml.load() 底层仍调用 Loader=FullLoader(可反序列化任意 Python 对象),而用户输入的 YAML 若含 !!python/object:exec 或 !!pickle 等标签,就能直接执行系统命令。
- 典型错误现象:
YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated - 真实风险示例:攻击者传入
!!python/object/apply:os.system ["id"],服务端解析时自动执行id - 根本原因:旧版默认行为是“方便”,新版默认行为是“安全”,但兼容性保留了危险入口
如何正确改用 yaml.safe_load()
safe_load() 只支持基础 YAML 类型(str、int、list、dict、bool、None),彻底屏蔽类构造、函数调用等危险操作,是绝大多数配置文件场景的唯一推荐方案。
- 直接替换:把所有
yaml.load(f)改成yaml.safe_load(f),无需额外参数 - 注意文件对象类型:如果读的是字符串,用
yaml.safe_load(yaml_str);如果是文件句柄,确保已打开为文本模式(open("x.yaml")即可,不用rb) - 若原逻辑依赖自定义类反序列化(极少见),不能强行用
safe_load(),需改用yaml.CSafeLoader或显式注册安全构造器,但应优先重构业务逻辑
哪些情况不能只靠 safe_load()?
当你的 YAML 文件本身包含非标准标签(如 !include、!env)或需要解析 datetime、float 等扩展类型时,safe_load() 会直接报错 yaml.constructor.ConstructorError。
- 常见报错信息:
could not determine a constructor for the tag 'tag:yaml.org,2002:timestamp' - 解决方案一(推荐):升级到 PyYAML ≥ 6.0,它对
safe_load()增加了部分内置类型支持(如timestamp、binary) - 解决方案二:使用
yaml.load(stream, Loader=yaml.CSafeLoader)(CSafeLoader 比 SafeLoader 更快,行为一致) - 绝对不要回退到
FullLoader或UnsafeLoader—— 即便你“信任输入源”,也违背最小权限原则
真正难处理的不是语法替换,而是识别项目里所有隐式调用点:比如第三方库内部是否用了 load(),或者封装了 yaml.load 的工具函数。建议全局搜索 import yaml 和 .load(,逐个确认。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











