mcpField
P
python-supply-chain

python-supply-chain

github.com/paldom其他239 次安装7 周前更新
代码仓库

关于 python-supply-chain

python-supply-chain 是一项用于为 GitHub 上的 Python 仓库添加多层供应链防护的技能,涵盖依赖更新、安全扫描、路径所有权控制以及 SBOM 和构建来源证明,并明确区分由配套技能负责的事项。

主要功能

  1. 01审计现有仓库控制措施
  2. 02配置依赖更新自动化
  3. 03扫描依赖、密钥与代码
  4. 04用 CODEOWNERS 保护自动化路径
  5. 05生成 SBOM 与来源证明

适用场景

  1. 01加固 Python 包仓库
  2. 02检查锁定依赖中的漏洞
  3. 03添加 GitHub 安全扫描
  4. 04准备软件清单与构建证明

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/paldom/python-skills --skill python-supply-chain

安装后在 Claude Code 中输入/python-supply-chain确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

evals/
evals.json
references/
dependabot.md
scanning-and-provenance.md
scripts/
check_supply_chain.py

详细介绍

python-supply-chain

在 GitHub 上的 Python 软件包仓库中安装分层供应链控制措施:带新鲜度延迟的依赖项更新自动化、漏洞和机密扫描、代码扫描、自动化相关路径的所有权规则,以及 SBOM/来源证明工件。此设计基于 2025–2026 年的事件浪潮(Shai-Hulud npm 蠕虫、由依赖项机器人传播的恶意 axios 版本、可变标签 Action 遭入侵):如今的攻击面是你的自动化,以及发布后的最初几小时——因此,以下任何单一控制措施都不足以应对,机器人产出的内容也应像人工 PR 一样受到审查。

不要在以下情况下使用

  • CI 质量门禁工作流、分支规则集、Action SHA 固定、zizmor——如果已安装 python-ci skill,这些由它负责。本 skill 只添加扫描和更新工作流,并说明哪些控制措施依赖规则集。
  • PyPI 可信发布(OIDC)和由标签触发的发布工作流——由 python-release skill 负责。本 skill 仅处理仓库端的 SBOM/来源证明;将软件包上传到 PyPI 的发布步骤应由该 skill 负责。
  • Pre-commit 钩子接入(包括本地 gitleaks 钩子)——由 python-precommit skill 负责。本地钩子仅供参考;本 skill 会安装强制执行的服务器/CI 层。
  • 打包和锁文件设置(uv init、pyproject.toml)——由 python-packaging 负责。
  • Agent 钩子/AGENTS.md 规则——由 agent-guardrails 负责。本 skill 仅通过 CODEOWNERS 保护 Agent 配置路径。
  • 超出基本凭据轮换范围的主动事件响应——升级给人工处理;不要尝试自动清理正在发生的入侵。

工作流

按顺序完成以下步骤;每一步都有独立价值,因此在用户要求的范围结束处停止。更改 GitHub 设置的步骤需要 gh 已通过身份验证,并在仓库上拥有管理员权限——否则请输出命令供用户运行。

1. 审查当前安全状况

在添加任何内容之前,从仓库根目录运行随附的只读检查器:

python3 "${CLAUDE_SKILL_DIR}/scripts/check_supply_chain.py" --root .           # file-level checks
python3 "${CLAUDE_SKILL_DIR}/scripts/check_supply_chain.py" --root . --github  # + GitHub-side settings via gh

(如果当前工作目录不同,请从此 skill 的文件夹中使用绝对路径调用。)它会为每项控制措施输出一行 PASS|WARN|FAIL|NOTE check: detail,并在出现 FAIL 时以非零状态退出。请在以下步骤中修复 FAIL;将 WARN 视为待办事项。不要重复添加已存在的控制措施——应对其进行调整。

2. 基线:提交锁文件

以下所有控制措施都假定依赖项集合已固定版本并提交:uv.lock(首选)、poetry.lock/pdm.lock,或使用哈希固定依赖项的 requirements(通过 pip-tools 使用 --generate-hashes)。如果没有锁文件,这是 python-packaging 的问题——请指出并停止;审计未固定版本的依赖项集合,审计的只是猜测。

3. 依赖更新自动化(Dependabot)

编写 .github/dependabot.yml:

version: 2
updates:
  - package-ecosystem: "uv"        # uv.lock projects; use "pip" for requirements/pip-tools/poetry
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 10
    cooldown:
      default-days: 7              # skip versions published < 7 days ago
    groups:
      python-minor-patch:
        update-types: ["minor", "patch"]   # majors stay individual PRs
  - package-ecosystem: "github-actions"    # keeps actions updated; pinning policy = python-ci
    directory: "/"
    schedule:
      interval: "weekly"
    cooldown:
      default-days: 7

关键决策详见 references/dependabot.md:

  • 冷却期是供应链控制手段,而不是更新计划:它会延迟采用新发布的版本,避开恶意版本通常被发现前的时间窗口;对于安全公告更新则会自动绕过冷却期——这就是它优于仅使用包管理器级新鲜度限制的原因。自 2026-07-14 起,github.com 默认应用 3 天冷却期,无需配置;default-days: 7 可用于主动延长冷却期(并与第 5 步的 exclude-newer 保持一致)。
  • 将次要版本和补丁版本分组,是解决 PR 过多问题的公认做法。主要版本不要分组,以便对破坏性变更进行单独审查。
  • 绝不要对机器人 PR 一概自动合并。 在 2026 年 4 月的恶意 axios 事件中,机器人发起的更新 PR 占 214 个中的 154 个,且约 60% 的机器人 PR 在未经人工审查的情况下合并。Dependabot PR 应与其他 PR 一样,要求 CI 检查通过并经人工审查。
  • 当用户需要以代码管理配置的灵活性时,Renovate 是可选方案;它对应的冷却机制是 minimumReleaseAge。相关权衡及其 pinDigest 陷阱见参考文档。选择一个机器人即可——同时运行两个会使通知量翻倍。
  • pip、uv、pre-commit 和 github-actions 生态系统支持冷却期(default-days 以及 pip/uv 的 semver-*-days);启用后,请确认更新 PR 确实会在下次计划运行时生成。
4. 锁文件漏洞审计(pip-audit)

审计从锁文件导出的项目固定依赖集:

uv export --format requirements-txt --no-emit-project -o /tmp/audit-req.txt
uvx --from pip-audit==2.10.1 pip-audit -r /tmp/audit-req.txt --no-deps

(==2.10.1 是示例固定版本——请查看 PyPI,确认当前版本并固定该版本。未固定版本的 uvx 会执行几分钟前刚发布的内容:这正是本技能要防范的攻击。)使用普通 pip 的备用方案是在项目环境中运行:python -m pip install pip-audit==2.10.1 && pip-audit。

  • 不要在没有 -r 的情况下直接运行 uvx pip-audit:它审计的是 pip-audit 自己的临时环境,而不是你的项目,并会为错误的目标报告无漏洞。
  • --no-deps 会跳过重新解析;由于导出文件中的版本已全部固定,因此这样做是正确的。
  • 按软件包报告发现的问题及其修复版本;不要盲目升级所有内容,也不要在自动化中使用 pip-audit --fix(它会修改环境,而不是锁文件)。
  • 备选方案:osv-scanner(Go 二进制文件)可直接读取 uv.lock;uv audit(自 2026 年 6 月起处于预览阶段,由 OSV 提供支持,可感知锁文件)稳定后将成为无需安装的选项——请固定你验证过的 uv 版本。
  • 持续审计:Dependabot 安全更新负责告警;仅当用户希望在 CI 中输出审计结果时,才添加定期扫描工作流(工作流示例见 references/scanning-and-provenance.md)。
5. 依赖解析新鲜度窗口(uv 项目)

对于 uv 项目,添加解析器级缓冲期,以避开刚发布的软件包:

[tool.uv]
exclude-newer = "2026-06-27T00:00:00Z"   # resolver ignores anything published after this

uv 也接受相对时间窗口——exclude-newer = "7 days"(或 ISO 8601 格式的 P7D);exclude-newer-package 可按软件包分别设置截止时间。设置后运行 uv lock。截止时间会比较每个构件的上传时间,而非发布日期,因此较晚上传的 wheel 会根据自身时间单独过滤。 有两点需要注意:固定时间戳会使解析结果停留在过去,直到有人更新它(请将更新操作加入发布检查清单);与 Dependabot 的冷却期不同,它也会延迟安全修复——因此两者都要使用:exclude-newer 保护笔记本电脑和 CI 上运行的 uv lock,冷却期保护机器人,而安全公告会绕过机器人的冷却期。参考文档:https://docs.astral.sh/uv/reference/settings/#exclude-newer。

6. 秘密扫描、推送保护和 CI 后备检查

GitHub 端的扫描对公共仓库免费且默认启用;私有仓库需要 GitHub Secret Protection 许可。启用/验证这两个开关:

gh api -X PATCH "repos/{owner}/{repo}" --input - <<'EOF'
{ "security_and_analysis": {
    "secret_scanning": { "status": "enabled" },
    "secret_scanning_push_protection": { "status": "enabled" } } }
EOF

推送保护会在检测到秘密时,在其进入历史记录之前阻止推送——这严格强于任何事后扫描——但 GitHub 文档说明,它只会阻止一部分高置信度模式。添加 CI gitleaks 扫描作为后备检查,它还能捕获通过 --no-verify 绕过本地钩子的情况(参考资料中包含工作流 YAML,以及 gitleaks-action 的组织许可注意事项)。如果发现任何秘密:首先轮换凭据;重写历史记录无法让已克隆、分叉或缓存的内容不再泄露。

7. 代码扫描(CodeQL)

对于纯 Python 仓库,默认设置就足够了(无需构建步骤):

gh api -X PATCH "repos/{owner}/{repo}/code-scanning/default-setup" -f state=configured

公共仓库免费;私有仓库需要 GitHub Code Security 许可。只有当用户需要控制查询包,或需要对工作流文件进行 language: actions 覆盖时,才使用参考资料中的高级工作流。将代码扫描结果设为合并阻止条件属于规则集的配置——交由 python-ci 处理。

8. 为定义自动化的路径设置 CODEOWNERS
# .github/CODEOWNERS — LAST matching rule wins (not first)
*                      @OWNER/maintainers
/.github/              @OWNER/platform-security
/.github/CODEOWNERS    @OWNER/platform-security
/AGENTS.md             @OWNER/platform-security
/CLAUDE.md             @OWNER/platform-security
/.claude/              @OWNER/platform-security

原因:能够编辑工作流、dependabot.yml 或 Agent 指令文件的人,可以绕过所有其他控制,因此这些路径需要比代码更严格的所有者。两个容易被忽略的问题:只有在分支保护/规则集中启用“要求代码所有者审核”后,CODEOWNERS 才会生效(这属于 python-ci 的职责——在交接时说明);没有写入权限的所有者会被忽略,且不会报错——请在 GitHub 上检查该文件的渲染视图,确认没有语法/所有者错误。

9. 安全状况仪表板(OpenSSF Scorecard,可选)

添加每周运行的 ossf/scorecard-action 工作流(YAML 见参考资料),即可通过 Security 选项卡中的 SARIF 结果,获得涵盖约十几项启发式检查的 0–10 分数。将其视为分流仪表板,而不是门禁:其维护者也称这些检查具有启发性,而追逐分数(例如固定无人审核的 SHA)被记录为安全作秀。在添加任何内容之前,公共仓库可以先到 https://scorecard.dev/viewer/?uri=github.com/OWNER/REPO 查看现有分数。

10. SBOM 和发布溯源证明

两种 SBOM 方案——根据受众选择:

# Repo-level SPDX from GitHub's dependency graph (compliance requests):
gh api "repos/{owner}/{repo}/dependency-graph/sbom" --jq .sbom > sbom.spdx.json

# Build-time CycloneDX from the lockfile (ship next to the wheel):
uv export --format requirements-txt --no-emit-project -o /tmp/sbom-req.txt
uvx --from cyclonedx-bom==7.3.1 cyclonedx-py requirements /tmp/sbom-req.txt -o sbom.cdx.json

对于发布版本,请在发布工作流中使用 actions/attest-build-provenance 为构建产物生成证明(并使用 actions/attest-sbom 为 SBOM 生成证明)——代码片段和所需权限见参考资料。发布工作流本身,以及通过可信发布生成的 PyPI 端证明,属于 python-release 技能。请如实告知用户其限制:证明只能证明产物在何处以及如何构建,并不能证明它是安全的——现实中曾发生过有效签名的恶意构建被发布的事件——而且只有在使用者进行验证时才有意义(gh attestation verify dist/pkg.whl --repo OWNER/REPO)。

11. 重新审计并交接

重新运行步骤 1;脚本应报告没有 FAIL。列出剩余的 WARN/NOTE 项,并为每项用一句话说明原因(有意跳过、需要许可,或属于相邻技能的职责范围)。

输出规范——完成状态

  • .github/dependabot.yml 中包含 pip 或 uv 生态系统条目、每周计划、冷却期、分组的次要/补丁更新,以及 github-actions 条目。
  • 已提交锁文件;记录了固定版本的 pip-audit 调用方式(或定期扫描)。
  • 已启用秘密扫描和推送保护(如果权限/许可受限,则向用户提供准确命令),并设置 CI gitleaks 后备检查。
  • 已启用 CodeQL(默认设置或已提交工作流)。
  • CODEOWNERS 覆盖 /.github/ 和 Agent 配置路径,并在交接说明中指出分支保护依赖项。
  • 根据范围可选:Scorecard 工作流、SBOM 产物、接入发布工作流的证明步骤(或委派给 python-release)。
  • scripts/check_supply_chain.py --root . 退出码为 0。

故障模式与注意事项

  • 不带 -r 运行 uvx pip-audit 会审计错误的环境(即该工具自己的临时 venv),并轻易报告零项发现。
  • Dependabot 冷却期可能卡住频繁发布的依赖项:筛选器只评估了最新版本,因此每周发布一次的依赖项可能永远不会提出更新(dependabot-core #14234/#14579;已部分修复——请验证当前行为)。 表现:依赖项在 Dependabot 状态一直为绿色的情况下,悄然过时数月。
  • 在包管理器层面设置冷却期会阻止安全修复;Dependabot 的冷却期不会(安全公告更新会绕过冷却期)。不要用前者替代后者。
  • 尚未证明冷却期对传递依赖有效(已确认 npm 存在此缺口,见 dependabot-core #14683;pip/uv 尚未验证)——第 4 步中的锁文件审计才是实际覆盖传递依赖的控制措施。
  • 机器人创建的 PR 不应获得未经验证的信任:攻击者会冒充 Dependabot 的品牌标识,而 axios 事件中,绿色检查通过后自动合并曾导致恶意软件上线。对待所有 PR 都应一视同仁地审查。
  • Dependabot 不会针对固定 SHA 的 Actions 发出警报(只针对 semver 标签)——这是本技能的警报机制与 python-ci 固定版本策略之间已知的差距;dependabot 的 github-actions 条目仍会提出固定版本更新,因此请保留该条目。
  • 组织仓库使用 gitleaks-action 需要许可证密钥 (GITLEAKS_LICENSE 密钥;个人账户可免费使用)——这是容易被忽略、且失败时不会发出提示的设置步骤。
  • CODEOWNERS 遵循最后匹配优先——末尾的 * 规则会覆盖上方的所有保护规则。请将兜底规则放在最前面,具体的安全路径规则放在后面。
  • 推送保护只是子集筛选器,并非保证——请保留 CI 后备检查。
  • Scorecard 可被操纵,且依赖启发式规则——绝不要将其设为合并门禁;由于 API 成本原因,其公开的每周扫描会省略多项检查(CI-Tests、Contributors、Dependency-Update-Tool),因此得分与本地运行结果不同。
  • 安装 Python 包会执行代码——安装时(构建后端、setup.py)和导入时都会执行。绝不要为了检查包而安装它;先在 https://inspector.pypi.io 上阅读其内容。注意拼写仿冒包(request 与 requests),以及大模型建议中编造的包名(slopsquatting)——在运行 uv add 前,请在 pypi.org 上核实准确的包名、仓库链接和发布历史。
  • 免费套餐边界:依赖关系图、Dependabot 警报和安全更新在所有仓库中均免费;密钥扫描和 CodeQL 仅对公开仓库免费——对于私有仓库,应让用户决定许可证事宜,而不是启用无法正常工作的开关。

文件

  • references/dependabot.md — 完整注释版 dependabot.yml、冷却期语义与错误详情、Renovate 对比、噪声调优、自动合并策略的依据。
  • references/scanning-and-provenance.md — gitleaks/TruffleHog CI 工作流、高级 CodeQL 工作流、Scorecard 工作流、含权限设置的 SBOM/证明代码片段、验证命令。
  • scripts/check_supply_chain.py — 只读安全态势审计;--github 会通过 gh 添加 GitHub 设置检查;FAIL 时以非零状态退出。

评论

支持 Markdown