事件经过

5 月 27 日,LiteLLM-Labs/lite-harness 公开仓库的一次提交里带上了 LiteLLM Agent Platform 的主密钥。团队很快发现并用 force-push 覆盖了提交,也识别出这批密钥需要吊销,但主密钥的吊销没有执行。这个密钥在公开历史里待了 136 天。

10 月 10 日,攻击者用这个主密钥访问 Agent Platform API,从一个管理 agent 的接口里读到了组织所有者的 GitHub CLI OAuth token。这个 token 没有绑定服务账号,也没有收窄权限,属于 2FA 之后的凭证,可以直接绕过不少敏感操作的身份复核。

拿到所有者权限后,攻击者向仓库推送临时分支、修改发布 workflow、把 staging 构建指向一个外观相似的仓库,还用第二个维护者的 token 通过了生产发布门禁。发布记录随后被删除,覆盖痕迹。

恶意包做了什么

微软的分析指出,受影响的 wheel 在 Python 启动路径上埋了钩子:应用不需要 import litellm,只要在受影响的环境里启动解释器,payload 就可能执行。一个采集器会扫描开发工具、AI 应用、云环境、浏览器和基础设施里的认证材料;另一个数据库模块则尝试读取 LiteLLM proxy 的凭证和模型配置。

  • PyPI:litellm==1.107.0 的 7 个 wheel,11:39 到 13:23 UTC 可下载;
  • Docker Hub:v1.107.0、latest、main-latest、main-stable 在 11:46 到 14:20 UTC 指向恶意镜像;
  • GHCR:同批标签在 13:51 UTC 前被替换;
  • 企业版私有发布不受影响,官方 v1.107.0 源码 tag 也不含恶意文件。

为什么难发现

攻击者没有改源码 tag,而是从自己控制的仓库构建;没有硬闯分支保护,而是用所有者 token 覆盖;没有留下明显的发布记录,而是把 run 删掉。对下游来说,版本号、包名、甚至部分校验都和正常发布很像,单看“我装的是官方包”并不足以自证清白。

现在该做什么

  • 查 lockfile、pip freeze、镜像 digest 与构建日志,确认是否命中 1.107.0 或上述标签;
  • 轮换 10 月 21 日前后在该环境出现过的 OpenAI、Anthropic、AWS Bedrock、Together 等密钥;
  • 不要在可疑环境里运行 python / pip 做“试探”,先隔离主机、离线取证;
  • CI 里的长期 token 换成短期、最小权限、绑定环境的凭证,发布门禁不要由单个人类 token 放行;
  • 对关键依赖固定版本 + 哈希,别让 latest 标签直接进生产。
主密钥泄露 136 天没人吊销,最后买单的是所有信任这个包的人。