-
Notifications
You must be signed in to change notification settings - Fork 519
PyYAML yaml.load(input) Deprecation
This page explains the PyYAML 5.1+ deprecation of the plain yaml.load(input)
function. See Footnotes.
Use of PyYAML's yaml.load
function without specifying the Loader=...
parameter, has been deprecated.
In PyYAML version 5.1+, you will get a warning, but the function will still work. See How to Disable the Warning below.
Before PyYAML 5.1+, the PyYAML.load
function could be easily exploited to call any Python function. That means it could call any system command using os.system()
. Here is a trivial example:
python -c 'import yaml; yaml.load("!!python/object/new:os.system [echo EXPLOIT!]")'
PyYAML's load
function has been unsafe since the first release in May 2006. It has always been documented that way in bold type: PyYAMLDocumentation. PyYAML has always provided a safe_load
function that can load a subset of YAML without exploit.
In 2017, a CVE was filed against PyYAML because it was capable of being exploited on untrusted input using the load
function, even though PyYAML was intentionally designed and documented to work that way from the start. The CVE seems to suggest that load
should use safe_load
by default. Since safe_load
only handles a subset of YAML, and PyYAML has been a very popular Python package for over a decade, this change is not feasible.
YAML is cross-programming language, data serialization language. PyYAML is an implementation of YAML that provides human friendly (plain text) data serialization for Python. Pickle is Python's native (binary) data serialization format. Pickle is also unsafe, and documented loudly as such. The author of PyYAML intentionally made it Pickle compatible.
Since load
cannot break backwards compatibility to call safe_load
, the maintainers of PyYAML decided to simply deprecate the plain usage of load
, and require that the user intentionally declare the Loader they desired. There are 4 loaders to choose from. See Below...
The load
function was also made much safer by disallowing the execution of arbitrary functions by the default loader (FullLoader).
NOTE The FullLoader loader class and
full_load
function (the current default forload
) should be avoided for now. New exploits in 5.3.1 were found in July 2020. These exploits will be addressed in the next release, but if further exploits are found then FullLoader may go away.
If you are simply using Python software that issues the "load() deprecation" warning, you should notify the authors of that software about it, so they can make and release the proper adjustments. One way to control/disable the warning is with the PYTHONWARNINGS
environment variable:
PYTHONWARNINGS=ignore::yaml.YAMLLoadWarning
You can read more about PYTHONWARNINGS
here.
If you are the author/maintainer of the Python code that is triggering the warning, the best way to stop getting the warning is to specify the Loader=
argument like so:
yaml.load(input, Loader=yaml.FullLoader)
The current Loader choices are:
-
BaseLoader
Only loads the most basic YAML. All scalars are loaded as strings.
-
SafeLoader
Loads a subset of the YAML language, safely. This is recommended for loading untrusted input.
-
FullLoader
Loads the full YAML language. Avoids arbitrary code execution. This is currently (PyYAML 5.1+) the default loader called by
yaml.load(input)
(after issuing the warning).WARNING: As of pyyaml-5.3.1 there are still trivial exploits. Do not use this on untrusted data for now.
-
UnsafeLoader
(also calledLoader
for backwards compatability)The original Loader code that could be easily exploitable by untrusted data input.
You may also use one of the shortcut "sugar" methods:
yaml.safe_load
-
yaml.full_load
(See FullLoader WARNING above) yaml.unsafe_load
If you are the author/maintainer of software that uses third party modules that trigger this warning, first make sure that their usage is safe for your application. Make sure they are aware of the warning. Then you can "globally" disable the warning with:
yaml.warnings({'YAMLLoadWarning': False})
This page will be kept up to date with the latest information about the load()
deprecation, usage and warnings.
The warning messages point to https://msg.pyyaml.org/load, which in turn should redirect you to here.