angular - 当默认加载器已经变得更安全时,为什么 PyYAML 5.1 会引发 YAMLLoadWarning?
问题描述
这是我的代码:
import yaml
yaml.load('foo')
此代码会导致 PyYAML (5.1) 出现以下警告。
$ pip install pyyaml
$ python3 foo.py
foo.py:2: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details.
yaml.load('foo')
所以我访问了https://msg.pyyaml.org/load以查看这是关于什么的,但我不明白需要这个警告。
首先,文档说,
UnsafeLoader
(也要求Loader
向后兼容)可以很容易地被不受信任的数据输入利用的原始加载程序代码。
好吧,这是有道理的。在早期版本中,原始加载程序是不安全的。此外,它说,
FullLoader
加载完整的 YAML 语言。避免任意代码执行。这是当前(PyYAML 5.1)由
yaml.load(input)
(发出警告后)调用的默认加载程序。
所以当前版本使用FullLoader
的是不是不安全的。这在文件中再次得到确认。
通过默认加载器 ( )禁止执行任意函数,加载函数也变得更加安全。
FullLoader
如果当前使用的版本FullLoader
不是不安全的,那我们为什么还需要YAMLLoadWarning
呢?
解决方案
我认为这个警告更像是一个通知和指导,让用户知道未来 PyYAML 的最佳实践是什么。回想一下:显式优于隐式。
在 5.1 版本之前(例如4.1),yaml.load
api 使用Loader=Loader
默认:
def load(stream, Loader=Loader):
"""
Parse the first YAML document in a stream
and produce the corresponding Python object.
"""
loader = Loader(stream)
try:
return loader.get_single_data()
finally:
loader.dispose()
def safe_load(stream):
"""
Parse the first YAML document in a stream
and produce the corresponding Python object.
Resolve only basic YAML tags.
"""
return load(stream, SafeLoader)
那时,Loader
类只有三种可用的选择:limitedBaseLoader
和SafeLoader
unsafe Loader
。虽然默认的是不安全的,就像我们从文档中读到的一样:
PyYAML 的
load
功能自 2006 年 5 月首次发布以来一直是不安全的。它一直以粗体显示:PyYAMLDocumentation。PyYAML 一直提供一个safe_load
可以加载 YAML 子集而不被利用的函数。
但是仍然有很多资源和教程更喜欢yaml.load(f)
直接使用,因此用户(尤其是新用户)正在隐式选择默认的 Loader 类。
从 PyYAML 版本5.1开始,yaml.load
api 被更改为更明确:
def load(stream, Loader=None):
"""
Parse the first YAML document in a stream
and produce the corresponding Python object.
"""
if Loader is None:
load_warning('load')
Loader = FullLoader
loader = Loader(stream)
try:
return loader.get_single_data()
finally:
loader.dispose()
def safe_load(stream):
"""
Parse the first YAML document in a stream
and produce the corresponding Python object.
Resolve only basic YAML tags. This is known
to be safe for untrusted input.
"""
return load(stream, SafeLoader)
并且一个新FullLoader
的被添加到Loader
类中。作为用户,我们还应该了解这些变化并yaml.load
更明确地使用:
yaml.load(stream, yaml.SafeLoader)
推荐用于不受信任的输入。限制:加载 YAML 语言的子集。
yaml.load(stream, yaml.FullLoader)
获得更可信的输入。还有一点限制:避免任意代码执行。
yaml.load(stream, yaml.Loader)
(UnsafeLoader
与 相同Loader
)不安全。却拥有十足的实力。
推荐阅读
- python - 如何在一个函数中替换数据后连接两个熊猫数据框
- javascript - Array.prototype.fill 在 Array.prototype.map 中的异常行为
- sockets - 使用未绑定或绑定但不监听的套接字
- scala - 将数据从 Amazon redshift 加载到 HDFS
- arrays - 要在 nodeJs 的新行中显示的数组值
- php - 多个相同实体关系
- python - write_csv_rows() 在具有长字符串的大型数据集上非常慢
- c# - ASP.NET Core 2.1 代码生成错误 - 找到多个相同类型的自定义属性
- entity-framework-core - EF 核心,创建自定义默认约束名称
- twitter - Twitter API 返回推文链接,而推文没有链接