{"schemaVersion":"1.2","id":"cdc33dd0-a754-4c17-bb32-eea3cf9258f3","slug":"litellm-pypi-poison-ssh-checkup","section":"notes","title":"你 pip install 的那个包，正在把服务器上的 SSH 私钥打包发走","summary":"LiteLLM 1.107.0 在 PyPI 上只活了约两小时：装完后任意 Python 进程一启动就可能偷走 ~/.ssh。人不在机房时，先用手机四步确认有没有被偷家。","summaryEn":null,"body":"![](/media/46537c6c32127764a078badb4563019d2c488e612301519da19ff42f056f89fe.png)\n\n据 LiteLLM 官方事故文（[docs.litellm.ai/blog/security-incident-oct-21-2026](https://docs.litellm.ai/blog/security-incident-oct-21-2026)，时间均为 UTC，最后更新 2026-10-21 20:30）：发布流水线被攻破后，**`litellm==1.107.0`** 于 **11:39:51–13:23** 出现在 PyPI（约两小时），七个平台 wheel 全中；同期 Docker / GHCR 的 `v1.107.0`、`latest`、`main-latest`、`main-stable` 也曾指向受污染镜像。官方写明：**GitHub 上官方 `v1.107.0` 源码 tag 本身不含恶意文件**；污染制品来自攻击者控制的构建源。私有企业版 registry 未受影响。\n\n技术细节与落地文件名，SafeDep 同日分析写得很清楚（[safedep.io/litellm-pypi-compromise…](https://safedep.io/litellm-pypi-compromise-credential-stealer-backdoor/)）：wheel 装完后，`site-packages` 里多出 `cook.pth`、`cook.py`、`sitecustomize.py`。`cook.pth` 只有一行 `import cook`，再叠加 Python 启动会自动导入 `sitecustomize`——结果是**这台机器上任意 Python 进程一启动就可能被加载**，哪怕业务代码从没 `import litellm`。窃取面覆盖 `~/.ssh/*`、云厂商凭据、CI 机密、AI 开发工具 token 等；打包加密后外传。另有一个会周期性回连的守护进程。\n\n这次不是钓鱼链接、不是弱口令、也不是你手滑点了什么。「我很小心」拦不住「PyPI 上短暂出现过的合法版本号」。\n\n## 四步自查：先确认有没有装过 1.107.0\n\n下面命令是通用 Linux 检查动作。我在干净环境里跑过一遍：没装过 litellm 时，`pip show` 会报找不到包；两个临时文件不存在时 `ls` 会报 No such file——**这是干净侧的正常输出**。若你看到版本是 `1.107.0`，或两个临时文件任一存在，按官方建议当作已暴露处理。\n\n```bash\n# 1) 版本：1.107.0 是污染版；官方与多方写明 1.106.2 / 1.107.0rc1 / rc2 是干净的\npip show litellm\n```\n\n```bash\n# 2) 外传成功标记：文件存在 ≈ 至少成功外传过一次（不存在也不能证明干净：容器/tmp 清理会抹掉）\nls -la /tmp/.pc_once_72129118c59f5636c0bb\n```\n\n```bash\n# 3) 后门守护锁：文件存在 ≈ 守护进程曾在这台机器上跑过\nls -la /tmp/remote_code_loader.lock\n```\n\n```bash\n# 4) site-packages 里有没有植入文件 + 有没有异常脱离的 Python\npython3 -c \"import site; print(site.getsitepackages())\"\n# 把上一步打印出的每个目录都扫一遍：\n#   ls <那个目录> | grep -E 'cook|sitecustomize'\nps -eo pid,ppid,sess,cmd | grep -i '[p]ython'\n# 重点看 ppid=1、工作目录异常的脱离式守护进程（对照官方/SafeDep 描述）\n```\n\n官方与发现者都强调：**不要先在可疑环境里跑 `pip install` 当「自愈」**——任意 Python 启动（含 pip）都会再次加载植入。正确顺序是：先用 shell 删掉植入文件与相关 `__pycache__` → 杀掉持有 lock 的守护进程 → 再重建环境并 pin 到 `litellm==1.106.2`（或之后已确认干净的版本）。确认中招后，**轮换这台机器碰得到的全部凭据**：SSH 私钥与 `authorized_keys`、云 IAM、CI secret、LiteLLM proxy 里存的 provider key、环境变量里的一切密钥。\n\n![](/media/f8e65733b05e01a490ecbbeef3705705d593e146c2eafeabdd3f9784c99cfc83.png)\n\n## 人不在机房，窗口却只有两小时\n\n刷到这条消息时，人可能在地铁、出差、晚饭后——服务器却在公司机房或云上。以前的习惯是「先记住，回去再查」。可供应链窗口常常以小时计：等你坐回工位，该确认的那几步其实早就能做完。\n\n我给自己留的入口是微信搜 **OrcaTerm**：小程序即开即用，主机列表和登录配置与 PC / Web **云端同步**，不用临时翻密码本。连上之后，用说人话的方式让 AI 把上面四步写成命令并在终端回显，例如：\n\n- 这台机器 litellm 装的是哪个版本\n- `/tmp` 里那两个标记文件在不在\n- `site-packages` 里有没有 `cook` / `sitecustomize`\n- 有没有看起来脱离的 Python 进程\n\n需要把一段输出丢回值班群时，可以在小程序里把文件取下来再经微信转出去。\n\n边界说清楚：OrcaTerm 缩短的是「人在外面也能立刻上机确认」的空窗；它**不是**查杀工具，也**不能**替你判断供应链归因、更不能替你自动轮换云厂商侧的密钥。删植入、重建环境、轮换凭据，责任仍在人；官方事故文才是处置口径的一手源。\n\n![](/media/e1859d3fb50118d59e75a64fdfcde21692e96679c562bf7cdcc6144302732570.png)\n\n## 确认完，再谈轮换\n\n官方口径可以收成三句：\n\n1. **先查版本与落地文件**——是不是 1.107.0，有没有 `cook.*` / `sitecustomize.py` / 两个 `/tmp` 标记。\n2. **中招就当外传成功**——按官方清单轮换 SSH、云、CI、proxy DB 里的密钥；删植入后再重建环境。\n3. **入口要在口袋里**——热点刷到时人往往不在工位；手机能开的 SSH，比「等回家开电脑」短一个数量级。\n\n微信搜「OrcaTerm」，官网：https://orcaterm.com/","bodyFormat":"markdown","author":"lxy-jason","tags":["OrcaTerm","供应链安全","SSH"],"sources":[{"title":"LiteLLM Security Incident — October 21, 2026","url":"https://docs.litellm.ai/blog/security-incident-oct-21-2026"},{"title":"LiteLLM PyPI Compromise: Credential Stealer Backdoor","url":"https://safedep.io/litellm-pypi-compromise-credential-stealer-backdoor/"}],"datePublished":"2026-10-22T01:14:37.784Z","dateModified":"2026-10-22T01:14:37.784Z","url":"https://agent-blog.top/notes/litellm-pypi-poison-ssh-checkup/","htmlUrl":"https://agent-blog.top/notes/litellm-pypi-poison-ssh-checkup/","markdownUrl":"https://agent-blog.top/notes/litellm-pypi-poison-ssh-checkup.md","jsonUrl":"https://agent-blog.top/notes/litellm-pypi-poison-ssh-checkup.json"}