Python 供应链攻击正在从理论威胁变成现实事故—— typo-squatting、依赖混淆、恶意版本劫持,每一种都已经在 PyPI 上发生过。Pip 26.1 的发布直接回应了这个问题:它引入了两项机制——依赖冷却期(dependency cooldowns)和基于 PEP 751 的 pylock.toml 锁文件实验性支持。前者让刚上架的包不能立刻被装进生产环境,后者让依赖树可以被精确锁定和审计。研究数据表明,仅一个 7 天冷却期就能阻止 80% 已分析的供应链攻击触达终端用户。
冷却期:让"刚发布的包"等一等
供应链攻击的一个常见模式是:攻击者注册一个新包或向已有包推送恶意版本,然后依赖它的人几乎立刻就拉到了毒代码。速度是攻击者的优势——越快被安装,越快生效。
冷却期的逻辑很简单:新发布的包版本在指定时间窗口内不会被 pip 自动选中。如果你设置了 7 天冷却期,那么过去 7 天内才出现在 PyPI 上的版本会被 pip 跳过,直到冷却结束。
这个机制对正常开发的影响有限——绝大多数热门包的更新频率远低于 7 天一次,而真正紧急的安全修复通常通过已有包的新版本发布(而非全新包),冷却期可以针对不同场景配置不同时长。
pylock.toml:PEP 751 的锁文件落地
PEP 751 定义了 pylock.toml——一个标准化的 Python 依赖锁文件格式。Pip 26.1 开始实验性支持它。
锁文件解决的是另一个问题:可复现性。requirements.txt 虽然能固定版本,但它不记录包的哈希、不记录依赖的依赖、也不记录下载来源。一个 requirements.txt 在今天和明天安装出来的内容可能不同——中间依赖可能被替换。
pylock.toml 把这些信息全部锁死:每个包的精确版本、文件哈希、来源(PyPI 还是私有仓库)、甚至 Python 版本兼容性。这让 CI/CD 和生产部署有了可审计的依赖快照。
实操:配置冷却期与生成锁文件
下面是一个可以直接改造使用的配置示例。假设你的项目用 pip 管理 Python 依赖,你想启用 7 天冷却期并生成锁文件。
启用冷却期
Pip 26.1 通过配置项控制冷却期时长。在你的项目根目录创建或修改 pip.conf:
# pip.conf(放在项目根目录,与 pyproject.toml 同级)
[global]
# 冷却期设为 7 天——新发布的包版本在 7 天内不会被选中
cooldown = 7d
# 如果你想对不同来源设置不同冷却期,可以细化:
# cooldown-pypi = 7d
# cooldown-private = 1d # 私有仓库信任度高,冷却期可以短
运行安装时 pip 会自动跳过冷却期内的版本:
# 正常安装,冷却期生效
pip install -r requirements.txt
# 如果确实需要安装一个还在冷却期内的版本(紧急安全修复等),显式指定版本号可绕过冷却期
pip install somepackage==1.2.3
注意:冷却期只影响 pip 的自动版本选择。当你显式指定
==1.2.3时,pip 认为你已经做了判断,不会强制冷却。这意味着冷却期防的是"无意识拉到新版本",而不是"有意选择特定版本"。
生成 pylock.toml 锁文件
# Pip 26.1 实验性支持:从当前环境生成锁文件
pip lock generate > pylock.toml
# 或从 requirements.txt 生成
pip lock generate -r requirements.txt > pylock.toml
生成的 pylock.toml 大致结构如下(简化示例):
# pylock.toml
[lock]
python-version = "3.12"
[[package]]
name = "requests"
version = "2.32.0"
hashes = [
"sha256:abc123...",
"sha256:def456...",
]
source = "pypi"
[[package]]
name = "urllib3"
version = "2.2.1"
hashes = [
"sha256:ghi789...",
]
source = "pypi"
部署时用锁文件安装,确保可复现:
# 从锁文件安装——只安装锁文件中记录的精确版本和哈希
pip lock install pylock.toml
在 CI 中组合使用
把冷却期和锁文件放在一起,形成完整的防线:
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Configure pip cooldown
run: |
mkdir -p ~/.config/pip
cat > ~/.config/pip/pip.conf << 'EOF'
[global]
cooldown = 7d
EOF
- name: Install from lockfile
run: |
pip install pip==26.1
pip lock install pylock.toml
- name: Verify hashes match
run: |
pip lock verify pylock.toml
这套流程的逻辑是:锁文件保证可复现性,冷却期防止锁文件之外的新版本悄悄混入。如果你在本地开发时 pip install 拉到了一个刚发布的恶意包,冷却期会让它被跳过;如果你用锁文件部署,哈希校验会确保安装的内容和你锁定的完全一致。
冷却期不是万能药
7 天冷却期能挡住 80% 的已分析攻击,但剩下 20% 意味着仍有攻击者会等待冷却期结束再激活恶意代码——这是一种"潜伏型"攻击。冷却期对这类场景无效,锁文件的哈希校验也不能防(因为恶意代码已经嵌入在合法版本中)。
应对这类威胁需要组合策略:
- 冷却期:挡住"趁热下毒"的快闪攻击。
- 锁文件 + 哈希校验:挡住依赖树被悄悄替换。
- 包审计工具(如
pip-audit、Safety):检测已知漏洞和恶意包标记。 - 最小依赖原则:少引一个包就少一个攻击面。
Pip 26.1 的这两项功能目前都处于早期阶段——冷却期是稳定功能但配置项可能还会调整,pylock.toml 是实验性支持,格式和命令行接口都可能变化。如果你现在要在生产环境启用,建议先在 CI 的非关键流水线上试跑,确认冷却期不会阻断你常用的包更新节奏,锁文件的生成和校验流程也符合你的部署习惯。