3 ноября 2026 года команда Django выпустила исправления для всех поддерживаемых веток: 6.1.3, 6.0.10 и 5.2.19. В них закрыты шесть уязвимостей. Пять разработчики оценили как низкие, одну, SSRF через GeoJSON, как среднюю. Обновиться советуют как можно скорее.
Большая часть дыр сидит в GeoDjango, то есть касается проектов с картами и геоданными. Но две затрагивают почти любой сайт на Django: загрузку файлов и кэширование страниц. Ещё одна важна тем, кто дал коллегам доступ в админку только на просмотр.
Загрузка файлов в base64 могла съесть память: CVE-2026-108147
Встроенный разборщик форм MultiPartParser принимал части запроса с заголовком Content-Transfer-Encoding: base64 и держал такой файл целиком в памяти. Ограничение FILE_UPLOAD_MAX_MEMORY_SIZE, которое обычно заставляет Django сбрасывать крупные загрузки во временный файл, на них не действовало. На практике это значит, что большой запрос на любую форму с загрузкой может раздуть процесс воркера.
Пока обновление не выкатили, помогает ограничение размера тела запроса на веб-сервере, например client_max_body_size в nginx. Оно и так стоит почти везде, но стоит проверить, что там не гигабайты.
Кэш мог отдать чужую страницу: CVE-2026-113593
Промежуточный слой UpdateCacheMiddleware и декоратор cache_page() строили один и тот же ключ кэша для запроса без заголовка из Vary и для запроса, где этот заголовок есть, но пустой. Если страница зависит, скажем, от Cookie или Authorization, ответ, закэшированный для одного запроса, мог уйти другому. Отсюда и риск утечки личных данных.
Теперь отсутствующий и пустой заголовок дают разные ключи, как требует RFC 9111. После обновления старые записи для запросов без заголовка просто перестанут находиться и закэшируются заново, так что первое время нагрузка на базу может немного подрасти.
Хеш пароля в админке для тех, кто только смотрит: CVE-2026-113733
Сотрудник с правом только на просмотр модели пользователей видел в админке хеш пароля целиком. Это случалось, если модель с паролем не указана в AUTH_USER_MODEL или если AUTH_USER_MODEL наследует поле password от другой модели через многотабличное наследование. Сам пароль по хешу не прочитать, но перебирать его офлайн уже можно. Исправление есть в 6.1.3 и 6.0.10, ветку 5.2 эта проблема не затрагивает.
Три уязвимости в GeoDjango, одна средняя
Самая серьёзная в выпуске, CVE-2026-111362, связана со старой возможностью формата GeoJSON указывать систему координат ссылкой в поле crs. Библиотека GDAL по такой ссылке до сих пор ходит. Поэтому если геометрия из пользовательского ввода попадала в форму, проверку, сохранение или запрос к базе, злоумышленник мог заставить сервер сделать сетевой запрос от имени процесса Django или прочитать файл. Теперь поиск по геополям, поле формы GeometryField и GEOSGeometry отклоняют GeoJSON со ссылками на внешние ресурсы. Утилиты DataSource и LayerMapping для загрузки своих, доверенных данных такие файлы по-прежнему принимают.
Похожая история с CVE-2026-114582: SpatialReference передавал строку прямо в GDAL, а тот умеет открывать по ней URL и файлы. То же касалось методов transform() у GEOSGeometry, OGRGeometry и GDALRaster и установки srs и srid. Если такую строку мог задать пользователь, по исходящим запросам можно было вытянуть содержимое локальных файлов. Теперь сетевой и файловый доступ при разборе строки отключён, но полностью это работает только с GDAL 3.9 и новее. Для недоверенного ввода разработчики советуют передавать целочисленный SRID, а на старом GDAL сверять строку со списком разрешённых. Новая системная проверка gis.W001 предупредит, если GDAL старше 3.9.
Третья, CVE-2026-111211, мелкая: GeometryField и его виджеты писали неверные значения из формы в лог как есть, вместе с переводами строки и ANSI-последовательностями. Так можно подделать записи в логе или испортить вывод в терминале.
Как проверить и обновить
Версию смотрим в том окружении, где крутится проект:
python -m django --version # или pip show django | grep -i ^version # версия GDAL для GeoDjango python -c "from django.contrib.gis.gdal import gdal_full_version; print(gdal_full_version())"
Внутри своей ветки это обычный патч-релиз, обновляемся как всегда:
# ветка 6.1 pip install -U "django>=6.1.3,<6.2" # ветка 5.2 LTS pip install -U "django>=5.2.19,<6.0" # в проектах на uv uv lock --upgrade-package django && uv sync # после обновления python manage.py check
Кроме исправлений, 6.1.3 добавляет совместимость с Python 3.15. Ветка 5.2 при этом остаётся LTS, на неё исправления будут приходить дольше всего.
В итоге: выпуск без паники, но с двумя вещами, которые касаются почти всех. Это загрузка файлов в обход лимита памяти и кэш, который мог перепутать ответы. Владельцам проектов на GeoDjango обновиться нужно в первую очередь и заодно проверить версию GDAL. Подробности по каждой уязвимости есть в заметках к 6.1.3.
