requirements.txt:核心工具还是隐藏威胁?
每个 Python 项目都有它。那个看似无辜的 requirements.txt 位于你的仓库根目录下的文件 pip install requirements.txt 消耗,是一个依赖项列表,当然,但如果你不小心,它也可能成为不稳定构建、易受攻击的软件包和严重安全问题的大门。
从本质上讲, requirements.txt 控制应用程序引入哪些第三方包。运行 pip install -r requirements.txtPython 的包管理器会安装列出的所有依赖项。但问题是:如果你没有指定确切的版本,那么 信任 PyPI 每次都提供安全、兼容且未经修改的版本。现代 AppSec 并非如此运作。
如果没有固定,构建可能会中断。更糟糕的是,你的应用程序可能会在不知不觉中摄入恶意包。开放式版本控制(Flask >=1.0, 例如)或宽松的版本约束(django~=3.2) 是注入不安全代码的沃土。因此,需要妥善管理 requirements.txt 是一项核心安全任务。
pip freeze 和 pip install requirements.txt 的详细内容
点冻结 虽然很方便,但如果不理解它捕获的内容,使用起来也很危险。开发人员经常会生成 requirements.txt 使用 pip freeze 要求.txt,期望它能锁定他们的环境。但冻结并不会验证依赖项的安全性或来源;它只会转储当前安装的所有内容,包括过渡包和可能已过期的包。
现在想象一下你的队友或你的 CI 盲目地运行 pip install -r requirements.txt。如果该文件包含已弃用的、易受攻击的,甚至 域名抢注的软件包,您刚刚自动化了一次安全事件。
简单示例:
# Developer's freeze output
pip freeze > requirements.txt
boto3==1.24.20
requests==2.27.1
⚠️ 不安全的示例,请勿在生产中使用
现在将其添加到您的 CI pipeline:
- name: Install dependencies
run: pip install -r requirements.txt
你相信环境是可重现的,PyPI 中没有任何变化,并且 每个依赖项 仍然是安全的。这是一个巨大的假设,当依赖于 pip freeze 要求.txt 工作流程。
真正的 AppSec 威胁:requirements.txt 中的域名抢注和依赖混淆
攻击者热衷于开源生态系统。为什么?因为开发者通常依赖默认设置和默认信任。以下是他们利用以下方式发起攻击: requirements.txt:
- 注册近似域名:上传一个名称类似这样的恶意包 请求 而不是 要求。关闭一个角色,您的构建就被拥有了。
请求#⚠️说明性示例,不是要安装的真实包
- 依赖混乱:如果您的内部软件包未固定或未设置私有作用域,攻击者可以将同名的恶意版本发布到 PyPI。如果您的 CI 未验证源代码,您将安装他们的软件包,而不是您自己的。
这两种攻击都利用了缺乏严格的固定和源代码控制 requirements.txt. 如果你的 只是说 一些内部库,然后运行 pip 安装要求.txt 在 CI 中,它可能会从错误的地方获取错误的包。
确保 requirements.txt 的安全 CI/CD Pipeline带有哈希和固定
以下是如何强化 requirements.txt 应对现实世界的威胁:
- 固定精确版本:始终使用 == 对于您包裹中的每个包裹 requirements.txt. 没有通配符,没有范围。
- 绝大部分储备使用 –require-hashes: 这使得 pip install -r requirements.txt 验证每个下载包的完整性。
计费示例:
flask==2.2.5 \
--hash=sha256:<actual_hash_here>
⚠️ 演示示例,实际项目中请替换为真实哈希
- 隔离你的构建:始终使用干净、精简的容器进行构建。切勿盲目信任基础镜像。
- 使用私有 PyPI 索引:托管您自己的代理/缓存并仅镜像受信任的包。
运行依赖项扫描:集成以下工具 点审计 或使用 SBOM基于您的分析 pipelines.
GitHub Actions 代码片段示例:
- name: Secure install
run: pip install --require-hashes -r requirements.txt
⚠️ 教育 pipeline 例如,适应你的环境
严格处理 pip install -r requirements.txt in CI/CD 是降低开源风险最简单的方法之一。
可重复的构建:保持其在不同环境下的稳定性
如果您的应用程序在本地运行,但在 staging 或 prod 中失败,则 requirements.txt 是常见的问题。即使是很小的版本偏差也会导致大问题。
使用以下策略:
- 点子工具: 使用 pip 编译 生成 requirements.txt 从 要求.in。它通过适当的固定来解决依赖关系。
- 环境标记:对于特定于操作系统的包或特定于 Python 版本的依赖项,使用类似 平台系统 == 'Linux'.
- Docker 缓存:在 CI 中,安装依赖项后缓存 Docker 层 requirements.txt 以减少构建的可变性。
pip-tools 示例:
# requirements.in
flask
# Compile
pip-compile requirements.in
⚠️ 演示示例,实际输出取决于您的环境
输出是完全固定的 requirements.txt.
像工具一样 点冻结,当与 pip install -r requirements.txt 在建造过程中,需要纪律和额外的保障措施。
结论:自信地锁定您的需求
管理不善 requirements.txt 这不仅仅是糟糕的做法,更是一种主动的安全风险。松散的固定、未经验证的安装以及对开放注册中心的盲目信任,都是攻击者利用你的 CI/CD pipeline。这些并不是理论上的缺陷;它们每天都在被利用。
依赖固定不仅仅是一种最佳实践。它是你抵御 Python 供应链攻击的第一道防线。结合 –require-hashes构建隔离和可重复的工具,例如 点子工具,你会得到一个 pipeline 这更难妥协。
是否使用 pip 安装要求.txt 无论是在本地还是在 CI 中,都要始终验证并监控构建过程中的内容。诸如 西吉尼 提供可见性、策略执行和自动检查,以锁定您的 Python 供应链 pip freeze 要求.txt 整个生产过程。





