4.x 中的重大更改是尝试解决CVE-2017-18342,这是对不受信任的输入执行任意代码的可能性。
在 PyYAML 4.x 中,dump
是一个别名safe_dump
,它不会处理任意对象:
>>> yaml.dump is yaml.safe_dump
True
Use danger_dump
对于旧的 3.x 行为。
>>> yaml.danger_dump(x)
'!!python/object/apply:numpy.core.multiarray.scalar\n- !!python/object/apply:numpy.dtype\n args: [i8, 0, 1]\n state: !!python/tuple [3, <, null, null, null, -1, -1, 0]\n- !!binary |\n AgAAAAAAAAA=\n'
同样适用于load
/safe_load
。找不到 4.1.0 的任何文档或发行说明,我只是通过挖掘提交才发现的(here).
PyYAML 不再支持这些对象类型有明确的原因吗?
Yes. yaml.load
允许任意代码执行,这样一个危险的功能只能选择加入,不可能意外使用。按理说,从一开始就应该是这样的。
在当前的 PyYAML 5.x 中:您可以指定 loader/dumper 类作为参数,而不是使用不同的函数:
yaml.dump(x, Dumper=yaml.Dumper) # like "danger dump"
yaml.dump(x, Dumper=yaml.SafeDumper) # like "safe_dump", won't dump python objs
与 3.x 一样,“危险”转储仍然是 5.x 中的默认值:
>>> yaml.dump(sys)
"!!python/module:sys ''\n"
>>> yaml.dump(sys, Dumper=yaml.SafeDumper)
RepresenterError: ('cannot represent an object', <module 'sys' (built-in)>)