依赖混淆攻击无法靠“一次配置”彻底杜绝,必须在安装、构建、运行三环节叠加校验机制,尤其要堵住setup.py和.pth文件的自动执行漏洞。

直接结论:依赖混淆攻击无法靠“一次配置”彻底杜绝,必须在安装、构建、运行三个环节叠加校验机制——尤其要堵住 setup.py 和 .pth 文件的自动执行漏洞。
为什么 pip install 会中招?看清依赖混淆的真实入口
依赖混淆不是 pip 本身有 bug,而是它默认信任索引源 + 优先匹配本地包名的逻辑被恶意利用。比如你项目里写了 requests-mock,但实际想用的是 requests-mock(官方维护);攻击者上传了同名但拼写微调的 requestsmock(少个连字符),pip 在未加约束时可能因缓存、镜像同步延迟或索引排序问题拉下毒包。
更危险的是,有些恶意包不靠名字混淆,而是在 setup.py 或 pyproject.toml 的构建阶段执行代码,或者通过 .pth 文件注册 Python 启动钩子——这些行为在 pip install 过程中就已完成,用户毫无感知。
- pip 默认不校验包来源签名,只比对包名和版本字符串
- 私有镜像若未开启元数据校验,会把恶意包当“合法缓存”同步过去
- CI/CD 中若用
pip install -r requirements.txt且未锁定哈希,每次构建都可能拉到不同内容
用 pip-tools 锁定哈希值,让安装行为可重现
仅靠 requirements.txt 写死版本号(如 requests==2.31.0)远远不够——攻击者可以劫持维护者账号,上传带毒的 2.31.0 版本(LiteLLM 1.82.8 就是这么干的)。必须强制校验每个包的 SHA256 哈希值。
操作步骤:
- 先用
pip-compile生成带哈希的锁定文件:pip-compile --generate-hashes requirements.in > requirements.txt - 部署时必须加
--require-hashes参数:pip install --require-hashes -r requirements.txt - 如果某包哈希不匹配,pip 会直接报错:
Hashes are required in --require-hashes mode, but they are missing,而不是静默跳过
注意:pip-compile 生成的哈希基于 PyPI 官方分发的 wheel 或 sdist,若你用了私有源,需确保其返回的包内容与官方一致,否则哈希校验失败。
禁用 setup.py 执行和 .pth 钩子,切断自动触发链
很多恶意行为发生在安装阶段,比如在 setup.py 里调用 os.system 下载 payload,或在 package.pth 中插入 import evil_hook。Python 3.12+ 已默认禁用 .pth 中的 import,但旧版本和部分打包工具仍支持。
安全加固建议:
- 在 CI/CD 构建环境里设置环境变量:
PYTHONNOUSERSITE=1(禁用用户 site-packages)、PIP_NO_BUILD_ISOLATION=0(强制隔离构建环境) - 用
pip install --no-deps --no-build-isolation先装基础构建工具,再用隔离环境编译依赖 - 扫描项目中是否存在
.pth文件:find . -name "*.pth" -type f,生产环境应禁止此类文件存在 - 检查
setup.py是否含可疑函数:exec、eval、subprocess.call、os.system、__import__等——可用bandit -r . --skip B101,B102快速过滤
运行时监控:发现已安装的恶意包不能只靠静态扫描
即使安装时一切正常,某些恶意包会在首次导入或 Python 解释器启动时才激活(比如 LiteLLM 的 .pth 钩子)。这时候静态扫描 requirements.txt 已经失效。
可行手段:
- 用
pip-audit检查已安装包是否在已知恶意包名单中:pip-audit --requirement requirements.txt - 结合
osv-scanner扫描运行时加载的包:osv-scanner --lockfile=requirements.txt - 在容器启动脚本中加入检测逻辑,例如检查
site-packages下是否有非预期的.pth或__pycache__目录 - 关键服务启动前,用
python -c "import pkg_resources; print([d for d in pkg_resources.working_set if 'evil' in d.project_name.lower()])"快速筛查异常包名
最易被忽略的一点:很多人以为只要没在 requirements.txt 里显式声明,就不会引入恶意包。但 setup.py 的 install_requires、pyproject.toml 的 dependencies、甚至 pip install 时的临时 URL,都可能悄悄带入间接依赖——所有这些路径,都必须纳入哈希锁定和运行时监控范围。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











