1. Django 6.0.7 这次修了什么,为什么值得你花十分钟自查
Django 6.0.7 和 5.2.16 是一次安全版本更新,核心修复三个低严重性问题,其中最容易被忽略的是缓存安全特性失效导致会话 Cookie 泄漏。这个问题的反直觉之处在于:Django 的缓存安全机制本来是为了防止会话 Cookie 被写进共享缓存,但它只在请求完全不携带任何 Cookie 时才生效。一旦你的项目里设置了语言偏好、主题偏好这类看起来无关紧要的 Cookie,这层保护就会静默失效,敏感的 sessionid 可能被缓存到共享缓存池里,被其他用户读到。
另外两个修复点分别是 GDALRaster 的缓冲区越界读取,以及 DomainNameValidator 的换行注入。前者影响使用 GeoDjango 处理栅格数据的项目,后者影响自定义域名校验逻辑。如果你只是普通 CRUD 项目,重点看第一个。
这篇不是发布说明的翻译,而是一条可跟做的验证路径:用 TaoToken 拿到模型通道的 Key 和 Base URL,让 Codex 读 Django 6.0.7 的发布说明,按分支列出修复点,再对照你项目里的 SESSION_COOKIE 和缓存配置,判断自己是否踩到这些分支。TaoToken 只提供 Key 和 Base URL,不替 Django 打补丁,补丁还是靠你升级版本。
适合谁:正在维护 Django 5.2.x 或 6.0.x 项目、用共享缓存(Redis/Memcached)做页面缓存、并且项目里设置了任意 Cookie 的开发者。如果你用的是本地内存缓存,风险面小很多,但配置检查仍然值得做一遍。
2. 前置准备:TaoToken Key 与 Codex 的 Base URL 配置
先打开 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 创建账号并生成 Key。这一步只做两件事:拿到一个 API Key,拿到 Base URL。Base URL 固定填 https://taotoken.net/api,注意结尾没有斜杠,也不要自己补/v1,Codex 侧会按它自己的约定拼接路径。
创建 Key 的入口在控制台里,生成后立刻复制保存,页面刷新后不再完整显示。如果你还没决定用哪种额度方式,短期验证用按量即可;如果你打算长期把 Codex 挂在项目里做代码审查和补丁对照,可以看 Coding Plan 的额度方案,入口在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。
配置 Codex 时,环境变量通常是这样组织的:
export OPENAI_API_KEY="你的 TaoToken Key" export OPENAI_BASE_URL="https://taotoken.net/api"如果你用的是 Codex CLI 的配置文件形式,等价写法是:
# ~/.codex/config.toml model = "gpt-5-codex" model_provider = "taotoken" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "OPENAI_API_KEY"这里有个容易踩的坑:base_url不要写成https://taotoken.net/api/v1,也不要写成带 UTM 参数的地址。UTM 只用于网页跳转统计,API 请求带上会污染路径。Key 的权限范围在控制台的 API Keys 页面管理,入口是 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。
配置完成后先别急着让它读发布说明,先用一条最小请求确认通道是通的,下一节给命令。
3. 可复制配置:让 Codex 读 Django 6.0.7 发布说明并按分支列修复点
第一步是验证通道。用 curl 发一条最小对话请求,确认 Key 和 Base URL 都对:
curl -s https://taotoken.net/api/chat/completions \ -H "Authorization: Bearer $OPENAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-5-codex", "messages": [ {"role": "user", "content": "回复 OK 两个字母即可"} ] }'返回体里能看到choices[0].message.content为OK,说明通道正常。如果返回 401,检查 Key 是否复制完整;返回 404,检查 Base URL 是否多写了/v1。
第二步是让 Codex 读发布说明。Django 的安全发布说明在官网的 weblog 里,你可以直接把链接或正文贴给它。更稳的做法是把发布说明正文保存成本地文件,再让 Codex 读文件,避免它凭记忆编造。提示词可以这样写:
读取当前目录下的 django-6.0.7-release-notes.txt。 按以下结构输出: 1. 每个漏洞的名称与严重性分级 2. 受影响的分支(6.0.x / 5.2.x) 3. 触发条件(什么配置下会命中) 4. 修复方式(升级到哪个版本) 不要总结成一段话,用表格。第三步是让它对照你的项目配置。把项目里的 settings 片段喂给它,重点是这几项:
# settings.py 片段 SESSION_COOKIE_SECURE = True SESSION_COOKIE_HTTPONLY = True SESSION_COOKIE_SAMESITE = "Lax" CACHES = { "default": { "BACKEND": "django.core.cache.backends.redis.RedisCache", "LOCATION": "redis://127.0.0.1:6379/1", } } MIDDLEWARE = [ "django.middleware.cache.UpdateCacheMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.cache.FetchFromCacheMiddleware", ]提示词:
这是我的 Django settings 片段。结合 Django 6.0.7 修复的缓存安全特性失效问题, 判断我的项目是否存在会话 Cookie 泄漏到共享缓存的风险。 逐项说明:哪些配置放大了风险,哪些配置缓解了风险,需要改哪一行。Codex 会指出关键点:UpdateCacheMiddleware和FetchFromCacheMiddleware同时启用时,整站缓存会介入;如果缓存后端是 Redis 这类共享缓存,且请求携带了任意 Cookie,缓存安全特性就可能不生效。它不会替你改代码,但会把判断依据列清楚。
4. 验证请求与成功结果:跑通一次对照检查
跑通一次完整请求后,你应该拿到一份结构化的对照结果。实测下来,一次合格的输出大致长这样:
| 漏洞 | 严重性 | 受影响分支 | 触发条件 | 修复版本 |
|---|---|---|---|---|
| 缓存安全特性失效导致会话 Cookie 泄漏 | 低 | 6.0.x / 5.2.x | 请求携带任意 Cookie 且使用共享缓存 | 6.0.7 / 5.2.16 |
| GDALRaster 缓冲区越界读取 | 低 | 6.0.x / 5.2.x | 使用 GeoDjango 处理特定栅格输入 | 6.0.7 / 5.2.16 |
| DomainNameValidator 换行注入 | 低 | 6.0.x / 5.2.x | 自定义域名校验未过滤换行符 | 6.0.7 / 5.2.16 |
拿到这张表后,对照你的项目做三件事。第一,确认 Django 版本,用python -m django --version或pip show django看当前版本号,低于 6.0.7 或 5.2.16 就需要升级。第二,确认缓存后端类型,本地内存缓存风险低,Redis/Memcached 这类共享缓存需要重点看。第三,确认是否有中间件在整站层面启用缓存,UpdateCacheMiddleware和FetchFromCacheMiddleware同时出现时要格外小心。
升级命令本身很简单:
pip install --upgrade "Django>=6.0.7" # 或者 5.2 分支 pip install --upgrade "Django>=5.2.16"升级后跑一遍测试:
python manage.py check --deploy python manage.py testcheck --deploy会顺带提示一批安全配置项,包括SESSION_COOKIE_SECURE、CSRF_COOKIE_SECURE、SECURE_HSTS_SECONDS等。它不会直接告诉你缓存安全特性是否生效,但能帮你把周边配置补齐。
如果你还想让 Codex 帮你验证模型通道本身是否稳定,可以到模型对话页面手动发一条请求做交叉确认,入口是 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite 。接入细节和参数说明在文档里,入口是 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。
5. 本篇常见错排查
报错一:401 Unauthorized。最常见原因是 Key 复制时带了空格或换行,或者环境变量没生效。用echo $OPENAI_API_KEY | wc -c看长度是否和生成时一致。另一个原因是 Key 被删除或额度耗尽,去控制台确认状态。
报错二:404 Not Found。九成是 Base URL 写错。正确值是https://taotoken.net/api,不要加/v1,不要加结尾斜杠,不要带 UTM 参数。Codex 的 provider 配置里如果写了base_url = "https://taotoken.net/api/v1",改成不带/v1的版本。
报错三:Codex 读不到本地文件。它只能读你明确给它路径或贴进对话的内容。把发布说明保存成文件后,用绝对路径或确认当前工作目录正确。如果它开始凭记忆编造漏洞名称,立刻打断,重新贴原文。
报错四:升级后测试失败。先看是不是第三方包对 Django 版本有上限约束,用pip check排查依赖冲突。GeoDjango 相关项目升级时注意 GDAL 版本兼容性,GDALRaster的修复涉及底层库调用,升级 Django 后建议跑一遍栅格相关测试。
报错五:判断不了自己是否受影响。关键判断链是:是否用共享缓存 → 是否启用整站缓存中间件 → 请求是否携带任意 Cookie。三者同时成立时风险最高。如果只满足前两条但请求从不带 Cookie,风险低;如果缓存是本地内存,风险也低。把这三条写进提示词让 Codex 逐条判断,比让它给一个笼统结论可靠得多。
报错六:把 TaoToken 当成补丁来源。它只提供 Key 和 Base URL,让 Codex 能请求模型通道,帮你整理补丁差异和配置对照。真正的修复动作是升级 Django 版本,这一步没有任何工具能替你完成。
6. 把这条验证路径固定成项目例行检查
一次跑通之后,你可以把这条路径固化成项目里的例行检查。做法是把发布说明文件、settings 片段、提示词模板放进一个security-review/目录,每次 Django 发安全版本时,用 Codex 跑一遍对照,输出一份差异表存档。长期做代码审查和 Agent 工作流的,可以看 Coding Plan 的额度方案,入口是 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。
如果你用 Claude Code 做类似的事,Anthropic 兼容接入的说明在 https://taotoken.net/claudecode-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claudecode-anthropic&utm_campaign=rewrite ,Base URL 同样填 https://taotoken.net/api。
最后留一个实用习惯:每次升级 Django 后,除了跑check --deploy,再手动确认一遍缓存中间件的启用状态和缓存后端类型。这两个信息决定了缓存安全特性是否真的在保护你的会话 Cookie,而它们不会出现在任何自动检查的报错里。