关键在构建前、构建中、构建后三道防线:构建前强制哈希验证并禁用不可信源;构建中在CI增加静态扫描与白名单校验;构建后需结合字节码反编译或沙箱动态执行检测零日后门。

做不到“彻底防范”,但能大幅压缩后门存活窗口——关键在构建前、构建中、构建后三道防线,缺一不可。
pip install 时如何阻断恶意包安装
默认 pip install 不校验包来源与签名,攻击者利用 typosquatting(如把 requests 拼成 requesrs)或劫持维护者账号发布带后门的版本,用户无感知就执行了 setup.py 中的恶意逻辑。
- 强制启用哈希验证:在
requirements.txt中每行末尾加上--hash=sha256:...,运行pip install --require-hashes -r requirements.txt;缺失哈希或哈希不匹配会直接报错HashMismatch - 禁用
--trusted-host和--index-url自定义源,除非你明确控制该镜像服务器(比如私有 PyPI) - 用
pip install --no-deps+ 手动控制依赖树,避免传递依赖自动拉取不可信包
CI/CD 流水线里怎么卡住带后门的构建
很多团队只在 PR 阶段扫 CVE,但后门代码往往不在 CVE 数据库里——它没被公开披露,甚至没被发现。光靠 pip-audit 或 safety 无法识别 setup.py 中的 os.system('curl ...') 这类行为。
- 在 CI 中增加静态扫描步骤:用
pylint --enable=exec,eval,subprocess-popen,os-system检查所有已下载包的源码(需先pip download到本地再扫描) - 禁止在构建阶段执行任意命令:Dockerfile 中避免
RUN pip install后立刻RUN python setup.py install,改用pip wheel --no-deps --wheel-dir ./wheels .预编译,再用pip install --find-links ./wheels --no-index - 对
setup.py、pyproject.toml中的build-backend和build-system.requires做白名单校验,例如只允许setuptools、poetry-core等已知安全构建后端
为什么只靠依赖扫描工具救不了命
pip-audit 和 safety 都基于已知漏洞数据库(NVD/CVE),而绝大多数后门是“零日”行为:没编号、没披露、没特征。它们可能藏在 __init__.py 的模块导入钩子中,或用 atexit.register() 在解释器退出时触发 payload,这些都不会被传统扫描捕获。
-
pip-audit只检查包名+版本是否出现在 CVE 列表中,不分析代码逻辑 -
safety同样依赖社区维护的漏洞规则集,滞后性强,对混淆变量名(如__import__('o'+'s').system(...))基本无效 - 真正有效的检测必须结合字节码反编译(如用
uncompyle6解出 pyc 中隐藏逻辑)或沙箱动态执行(如用py-sandbox限制网络/文件系统调用并监控异常行为)
最常被忽略的点:后门不一定在主包里——它可能藏在某个 extras_require 里(比如 requests[security] 实际装的是伪造的 urllib3-security)。不显式声明 extras、不锁定子依赖版本、不审计 pipdeptree --reverse 输出,等于主动给后门留门。

















