Почему PyYAML 5.1 вызывает YAMLLoadWarning, когда загрузчик по умолчанию уже сделан более безопасным? - PullRequest
2 голосов
/ 14 апреля 2019

Вот мой код:

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?

1 Ответ

4 голосов
/ 05 июня 2019

Я думаю, что это предупреждение больше похоже на уведомление и руководство, позволяющее пользователю узнать, какова лучшая практика 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 класса : ограниченный BaseLoader, SafeLoader и небезопасный Loader. Хотя по умолчанию это небезопасно, так же, как мы читаем из документа:

Функция PyYAML load была небезопасна с момента первого выпуска в мае 2006. Это всегда было задокументировано таким образом жирным шрифтом: PyYAMLDocumentation. PyYAML всегда предоставлял функцию safe_load, которая может загружать подмножество YAML без эксплойтов.

Но есть еще много ресурсов, и учебники предпочитают использовать yaml.load(f) напрямую, поэтому пользователи (и особенно новый пользователь) выбирают класс Loader по умолчанию неявно .


А поскольку версия PyYAML 5.1 , API yaml.load изменен, чтобы быть более явным :

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 more явно :

  • yaml.load(stream, yaml.SafeLoader)

    Рекомендуется для ненадежного ввода. Ограничение: загружает подмножество языка YAML.

  • yaml.load(stream, yaml.FullLoader)

    Для более надежного ввода. Еще одно ограничение: предотвращает выполнение произвольного кода.

  • yaml.load(stream, yaml.Loader) (UnsafeLoader совпадает с Loader)

    небезопасный. Но имеет полную силу.

...