Django 6.0.8 和 5.2.17 发布:修复四项安全问题

2026-08-04 35 预计阅读时间: 1 分钟
来源: djangoproject.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:9 分钟

Django 团队发布了 Django 6.0.8 和 5.2.17,修复四项安全问题,涉及 GIS 空间查询、语言代码缓存、嵌套几何集合,以及管理后台中的 URLField 渲染。官方建议所有使用受影响版本的项目尽快升级。

这次修复覆盖 Django main、6.1、6.0 和 5.2 分支。其中 Django 6.1 目前仍处于 release candidate 阶段,正式发行版用户主要需要关注自己所在的 6.0 或 5.2 支持线。

四个问题分别影响什么

1. 空间查询可能写文件或发起请求

CVE-2026-15307 的严重性为 high。空间 lookup 过去允许将某些 strdict 值传给 GDALRaster。根据栅格驱动的行为,这些值可能导致 Django 进程写入服务器文件,部分情况下甚至造成远程代码执行,也可能以 Django 进程身份发起网络请求。

问题之所以能够从管理后台触发,是因为 admin changelist 支持通过 ModelAdmin.lookup_allowed() 过滤数据。拥有某个注册模型查看权限的 staff 用户,如果该模型包含空间字段,就可能触及相关路径。

修复后,空间 lookup 不再接受以下类型:

  • dict
  • 不是有效 GEOSGeometry 的字符串,例如序列化字典

这是一个向后不兼容变化。需要注意,模型字段赋值不受这项限制影响,这些输入类型仍然可以用于字段赋值。但这不意味着它们可以直接信任:所有不受信任的用户输入,都应该在使用前完成校验。

2. 超长语言代码可能消耗内存

CVE-2026-15337 的严重性为 low。django.utils.translation.check_for_language() 会把语言代码作为内存缓存的 key。当攻击者提交大量不同且很长的语言代码时,缓存可能占用额外进程内存。

语言值可以通过 django.views.i18n.set_language() 视图的 POST 数据到达该函数,但这个视图默认并未启用。请求数据大小限制和缓存最大条目数已经让可消耗的内存受到约束;本次修复进一步拒绝长度超过 500 个字符的语言代码,并且在进入缓存查询前完成检查。

3. 深度嵌套的几何集合可能触发崩溃

CVE-2026-15830 的严重性为 moderate。向 GEOSGeometry 传入深度嵌套的 GEOMETRYCOLLECTION 可能导致 GEOS segmentation fault,形成拒绝服务风险。空间字段 lookup 和 GeometryField 表单字段也会受到影响。

现在默认限制如下:

  • WKT 格式最多嵌套 198 层 GEOMETRYCOLLECTION
  • WKB 格式中,深度和广度合计最多 198 个 GEOMETRYCOLLECTION

GEOSGeometry、表单字段和模型字段都支持通过新增的 max_geom_collections 参数调整限制。GeoJSON 输入不使用这项限制,因为 GeoJSON 由 GDAL 解析,受影响的解析路径不同。

4. 管理后台中的 URLField 可能导致 XSS

CVE-2026-15920 的严重性为 moderate。管理后台会在 changelist 和只读字段中把 URLField 值渲染成可点击链接。此前链接生成过程没有验证 URL scheme,因此数据库中已经存在的危险 URL 值可能被以链接形式输出。

修复后,display_for_field 会使用 URLValidator 验证 URLField 值。验证失败时,后台将值显示为普通文本,而不会生成链接。

升级方式

根据项目所在的 Django 支持线选择对应约束。Django 6.0 项目可以执行:

python -m pip install --upgrade "Django>=6.0.8,<6.1"
python manage.py check
python manage.py test

Django 5.2 项目可以执行:

python -m pip install --upgrade "Django>=5.2.17,<5.3"
python manage.py check
python manage.py test

如果项目通过 requirements.txt、锁文件或内部镜像管理依赖,还需要同步更新相应文件,并在干净环境中重新安装验证:

python -m pip install --requirement requirements.txt
python -m django --version
python manage.py check --deploy
python manage.py test

可以在部署前加入一个简单的版本检查,避免应用启动在低于安全版本的 Django 上:

# scripts/check_django_version.py
import sys

import django

minimum = (6, 0, 8)
current = django.VERSION[:3]

if current < minimum:
    raise SystemExit(
        f"Django {minimum[0]}.{minimum[1]}.{minimum[2]} or newer is required; "
        f"found {django.get_version()}"
    )

print(f"Django {django.get_version()} is supported")

上面的阈值只适用于 Django 6.0 项目。运行 Django 5.2 的项目应将 minimum 改为 (5, 2, 17),并结合项目的发布流程执行:

python scripts/check_django_version.py

升级后应重点检查的代码

升级本身只是第一步。GIS 项目应搜索所有空间 lookup 的构造位置,特别是把请求参数、查询字符串或管理后台过滤值直接传入 lookup 的代码。不要为了兼容旧行为而关闭新限制;更合理的做法是先将输入解析为明确的 GEOSGeometry,再执行查询,并限制输入大小和复杂度。

处理语言切换时,可以在应用层提前限制输入长度,减少无效请求进入业务逻辑:

from django.core.exceptions import ValidationError


def validate_language_code(value: str) -> str:
    if len(value) > 500:
        raise ValidationError("Language codes must be 500 characters or fewer.")
    return value

这段校验不能替代 Django 的安全修复,也不能假设语言代码只包含某一种格式。它适合作为表单、serializer 或 API 参数校验的一部分。

对于 URLField,应检查后台自定义展示函数、mark_safe()、自定义 ModelAdmin 列和只读字段。数据库中已有的 URL 值也值得审计,因为修复主要改变的是渲染时的安全判断,并不会自动清理历史数据。

实际采用建议

生产项目建议按下面的顺序处理:

  1. 确认当前 Django 版本和部署分支。
  2. 升级到 Django 6.0.8 或 5.2.17,具体取决于项目支持线。
  3. 在测试环境运行迁移检查、完整测试和 check --deploy
  4. 审计空间 lookup、语言切换入口以及后台 URL 展示逻辑。
  5. 检查数据库中的历史 URL 值和异常几何数据。
  6. 观察升级后的错误日志、内存使用和管理后台访问情况。

这次公告再次说明,Django 的安全边界不仅在视图函数中,也包括 admin 过滤器、GIS 解析器、表单字段和展示层。及时升级能获得官方修复,但输入校验、权限收敛和依赖版本锁定仍然需要由应用自身负责。


相关推荐