Pydantic 2.14.2 и последний 1.10.27: лишние поля обходили проверку, обновитесь

29 октября 2026 года команда Pydantic выпустила версию 2.14.2 и вместе с ней 1.10.27, последний выпуск ветки V1. Вместе они закрывают пять уязвимостей средней опасности: три позволяют обойти проверку данных, ещё две дают положить сервис слишком тяжёлым вводом.

Pydantic стоит почти в каждом современном Python-бэкенде: через него проверяют входящие данные FastAPI и многие другие библиотеки. Если ваш сервис принимает JSON от пользователей и вы где-то разрешили лишние поля через extra='allow', обновиться стоит в ближайшее время. Остальным достаточно поднять версию при следующем плановом обновлении.

Две дыры в Pydantic V2: лишние поля обходят проверку

Обе уязвимости V2 связаны с режимом, когда модель принимает поля, которые в ней не описаны. Обе получили 6,3 балла по CVSS 4.0.

Первая, GHSA-qpmf-fgh3-ff25, касается версий с 2.13.0 по 2.14.1. Если для лишних полей задан тип ключа, например __pydantic_extra__: dict[Annotated[str, Field(pattern=r'^x_')], int], то при разборе JSON через model_validate_json() ключи не проверялись вовсе. В модель могли попасть ключи, которые шаблону не соответствуют. Обычная проверка Python-словаря через model_validate() работала правильно.

Вторая, GHSA-3r8g-cqwr-jr29, затрагивает все версии V2 до 2.14.1 включительно. Речь о TypedDict и dataclass с псевдонимами полей (alias) и разрешёнными лишними данными. Если прислать одно и то же поле дважды, под псевдонимом и под настоящим именем, то проверенное значение затиралось непроверенным. В итоге поле, объявленное как int, могло оказаться строкой или чем угодно ещё. Модели на BaseModel эта дыра не задевает: там лишние поля хранятся отдельно.

Что ещё поменялось в 2.14.2

Исправление первой уязвимости заодно поменяло поведение: разбор JSON теперь ищет поля и лишние данные так же, как разбор Python-объектов. Ключ, который совпадает только с неиспользуемым именем или псевдонимом поля, теперь считается лишним, а не молча выбрасывается. В примере из заметок к выпуску модель с alias_generator=to_camel и extra='forbid' раньше получала {"page_size": 50} и тихо ставила значение по умолчанию 10, а теперь выдаёт ошибку extra_forbidden.

from pydantic import BaseModel, ConfigDict
from pydantic.alias_generators import to_camel


class Page(BaseModel):
    model_config = ConfigDict(extra='forbid', alias_generator=to_camel)

    page_size: int = 10


Page.model_validate_json('{"page_size": 50}')
# До 2.14.2: Page(page_size=10)
# С 2.14.2: ValidationError (extra_forbidden)

Так что после обновления стоит прогнать тесты API: клиенты, которые шлют поля в snake_case при camelCase-псевдонимах, могут начать получать ошибки. Полный список изменений поведения есть в pull request #13275.

Кроме этого, в выпуске обновили PyO3 до 0.30.1, jiter до 0.18.0 и speedate до 0.18.0, начали собирать колёса pydantic-core для PyPy 8.0, немного ускорили проверку и сериализацию моделей. Среди исправлений есть проверка max_length у словарей, защита от бесконечной рекурсии в validate_strings() и правильное глубокое копирование моделей, которые ссылаются сами на себя.

Pydantic 1.10.27: последний выпуск V1 и три исправления

Версия 1.10.27 официально последняя в ветке V1. После неё поддержка V1 заканчивается полностью, в том числе пространство имён pydantic.v1 внутри Pydantic V2, через которое многие проекты постепенно переезжали на новую версию. Те же три исправления вошли в pydantic.v1 из 2.14.2.

  • GHSA-r49w-vh47-r4hf: в dataclass V1 с Extra.allow достаточно было передать ключ __pydantic_initialised__, и Pydantic считал объект уже проверенным, то есть поля не проверялись вовсе.
  • GHSA-49g6-96jj-f7r9: проверка списка с unique_items=True занимала квадратичное время, и список в несколько сотен килобайт разбирался секундами. Теперь для списков из чисел, строк, байтов, bool и None проверка линейная. Для списков моделей и словарей она по-прежнему медленная, их размер лучше ограничить через max_items.
  • GHSA-jfv7-ghgv-gx4x: в регулярном выражении для длительностей ISO 8601 точка не была экранирована и совпадала с цифрами. Строка из нескольких десятков килобайт цифр в поле timedelta разбиралась секундами. Теперь разделителем дробной части считается только точка.

Две последние дыры дают устроить отказ в обслуживании: один запрос с большим телом надолго занимает процесс. Если сервис на V1 принимает данные снаружи, это повод не только обновиться до 1.10.27, но и всерьёз заняться переездом на V2, потому что новых исправлений для V1 больше не будет.

Как проверить свои проекты и обновиться

Сначала посмотрите, какая версия стоит в окружении, и найдите в коде места с разрешёнными лишними полями и старым pydantic.v1:

pip show pydantic | grep -i ^version
grep -rnE "extra *= *['\"]allow|Extra\.allow|extra_items|__pydantic_extra__" --include=*.py .
grep -rn "pydantic.v1" --include=*.py .

Обновление обычное. Для V2 нужна 2.14.2 или новее, для проектов, которые пока сидят на V1, хотя бы 1.10.27:

pip install -U "pydantic>=2.14.2"
# или через uv
uv add "pydantic>=2.14.2"
# для проектов на V1
pip install -U "pydantic>=1.10.27,<2"

Если версия зафиксирована в requirements.txt или lock-файле, поменяйте её там и пересоберите образы. Pydantic часто приезжает как зависимость фреймворка, поэтому проверьте и те окружения, где вы ставили его не напрямую.

В сухом остатке: Pydantic 2.14.2 закрывает два способа протащить непроверенные данные через лишние поля и делает разбор JSON строже, поэтому после обновления стоит прогнать тесты API. Ветка V1 получила последний выпуск 1.10.27 с тремя исправлениями, дальше её поддержки не будет.

Источники и ссылки


Комментарии загружаются…