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 с тремя исправлениями, дальше её поддержки не будет.