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. 04CODEOWNERS で自動化パスを保護
  5. 05SBOM と来歴証明を生成

活用シーン

  1. 01Python パッケージリポジトリの強化
  2. 02固定依存関係の脆弱性確認
  3. 03GitHub セキュリティスキャンの追加
  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 リリース、可変タグのアクション侵害)から導かれる設計上の前提は、攻撃対象領域が今や 自動化とリリース後の最初の数時間 にあるということです。そのため、以下の対策はいずれも単独では不十分であり、ボットが生成した出力も人間による PR と同じ疑いの目で扱います。

使用しない場合

  • CI 品質ゲートのワークフロー、ブランチルールセット、アクションの SHA ピン留め、zizmor — これらは、インストール済みであれば python-ci スキルが担当します。このスキルが追加するのは スキャン と 更新 のワークフローのみで、ルールセットに依存する対策についてはその旨を記載します。
  • PyPI のトラステッドパブリッシング(OIDC)とタグをトリガーとする公開ワークフロー — python-release スキルが担当します。このスキルの範囲は、リポジトリ側の SBOM/来歴までです。PyPI にアップロードする公開ステップはそちらに含まれます。
  • pre-commit フックの設定(ローカルの gitleaks フックを含む)— python-precommit スキルが担当します。ローカルフックは参考情報であり、このスキルではサーバー/CI 側の強制レイヤーを導入します。
  • パッケージングとロックファイルの設定(uv init、pyproject.toml)— python-packaging が担当します。
  • エージェントフック/AGENTS.md ルール — agent-guardrails が担当します。このスキルは CODEOWNERS を使ってエージェント設定パスを 保護する のみです。
  • クレデンシャルのローテーションの基本を超える 進行中のインシデント対応 — 人間にエスカレーションしてください。進行中の侵害に対する自律的なクリーンアップは試みないでください。

ワークフロー

各ステップには順番に取り組んでください。それぞれに独立した価値があるため、ユーザーの作業範囲に達した時点で終了します。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

(cwd が異なる場合は、このスキルのフォルダーから絶対パスを指定して実行してください。)各対策について PASS|WARN|FAIL|NOTE check: detail の形式で 1 行ずつ出力し、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件をボットが作成し、ボットのPRの約60%が人によるレビューなしでマージされました。他のPRと同様に、DependabotのPRにもCIと人によるレビューを必須にしてください。
  • Renovate は、設定をコードで柔軟に管理したい場合の代替手段です。クールダウンに相当する機能は minimumReleaseAge です。トレードオフと pinDigest の落とし穴についてはリファレンスを参照してください。ボットはどちらか一方を選んでください。両方を動かすとノイズが倍増します。
  • クールダウン(default-days と、pip/uv の semver-*-days)は pip、uv、pre-commit、github-actions の各エコシステムでサポートされています。有効化したら、次回のスケジュール実行で更新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 も個別に除外されます。 注意点は2つあります。固定日時を指定すると、誰かが更新するまで過去の状態で解決が固定されるため、リリースチェックリストに追加してください。また、Dependabot のクールダウンとは異なり、セキュリティ修正も遅らせます。そのため、両方を使います。exclude-newer はノートPCとCIでの uv lock 実行を保護し、クールダウンはボットを保護します。セキュリティアドバイザリーによる更新では、ボットのクールダウンがバイパスされます。リファレンス:https://docs.astral.sh/uv/reference/settings/#exclude-newer。

6. シークレットスキャン、プッシュ保護、CI によるバックストップ

GitHub 側のスキャンは無料で、パブリックリポジトリではデフォルトで有効です。プライベートリポジトリでは GitHub Secret Protection のライセンスが必要です。次の 2 つのトグルを有効にするか、状態を確認してください。

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

プッシュ保護は、検出されたシークレットが履歴に入る前にブロックします。これは事後スキャンよりも確実な保護ですが、GitHub の説明によると、ブロックされるのは信頼度の高いパターンの一部のみです。ローカルフックの --no-verify による回避も検出できるバックストップとして、CI の gitleaks スキャンを追加してください(ワークフロー 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、エージェントの指示ファイルを編集できる人は、他のすべての制御を回避できるため、これらのパスにはコードよりも厳格なオーナーを設定する必要があります。気づきにくい失敗が 2 つあります。CODEOWNERS は、ブランチ保護またはルールセットで「コードオーナーによるレビューを必須にする」を有効にするまで何も強制しません(python-ci の担当範囲なので、引き継ぎ時に伝えてください)。また、書き込み権限のないオーナーはエラーなしで無視されます。GitHub 上でファイルのレンダリング表示を確認し、構文やオーナーのエラーがないか確認してください。

9. セキュリティ態勢ダッシュボード(OpenSSF Scorecard、任意)

ossf/scorecard-action の週次ワークフロー(YAML はリファレンスを参照)を追加すると、約 12 種類のヒューリスティックに基づく 0〜10 のスコアと、Security タブの SARIF 結果を取得できます。これをゲートではなくトリアージ用のダッシュボードとして扱ってください。メンテナー自身もチェックはヒューリスティックだと説明しており、数値を追い求めること(例:誰も監査していない SHA をピン留めする)は、セキュリティ対策をしているように見せるだけだと文書化されています。パブリックリポジトリでは、何かを追加する前に https://scorecard.dev/viewer/?uri=github.com/OWNER/REPO で現在のスコアを確認できます。

10. SBOM とリリースの来歴証明

SBOM には 2 つの方法があります。対象ユーザーに応じて選んでください。

# 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 を使ってビルド済みの成果物に証明を付与してください(SBOM には actions/attest-sbom も使用します)。スニペットと必要な権限はリファレンスを参照してください。公開ワークフロー自体と、信頼された公開による PyPI 側の証明は python-release スキルの担当です。限界については正直に伝えてください。証明が示すのは成果物がどこでどのようにビルドされたかであり、安全であることではありません。実際に、有効な署名付きの悪意あるビルドが公開された事例もあります。また、利用者が検証しなければ意味がありません(gh attestation verify dist/pkg.whl --repo OWNER/REPO)。

11. 再監査して引き継ぐ

手順 1 を再実行してください。スクリプトで FAIL が報告されないはずです。残っている WARN/NOTE 項目と、それぞれの理由(意図的なスキップ、ライセンスが必要、または関連スキルの担当範囲)を 1 行ずつ列挙してください。

出力仕様 — 完了の条件

  • .github/dependabot.yml に pip または uv のエコシステムエントリ、週次スケジュール、クールダウン、マイナー/パッチ更新のグループ化、および github-actions のエントリがある。
  • ロックファイルがコミット済みで、pip-audit の実行方法が文書化され、バージョンが固定されている(またはスキャンがスケジュールされている)。
  • シークレットスキャンとプッシュ保護が有効になっている(権限/ライセンスが妨げとなる場合は、ユーザーに正確なコマンドを伝えている)。さらに、CI の gitleaks バックストップがある。
  • CodeQL が有効になっている(デフォルトのセットアップ、またはコミット済みのワークフロー)。
  • CODEOWNERS が /.github/ とエージェント設定のパスをカバーしており、ブランチ保護との依存関係が引き継ぎ時に伝えられている。
  • 対象範囲に応じて任意で追加:Scorecard ワークフロー、SBOM 成果物、リリースワークフローに組み込まれた証明ステップ(または python-release に委任)。
  • scripts/check_supply_chain.py --root . が終了コード 0 で終了する。

失敗しやすい点と注意事項

  • -r を付けずに uvx pip-audit を実行すると、誤った環境が監査されます(ツール自体の一時的な仮想環境)。その結果、問題がゼロだとそのまま報告されます。
  • Dependabot のクールダウンによって、リリース頻度の高い依存関係が更新されなくなることがあります:フィルターが評価するのは最新リリースのみなので、週次でリリースする依存関係では更新が提案されない場合があります(dependabot-core #14234/#14579。一部修正済み — 現在の動作を確認してください)。 症状:Dependabot が正常に動作しているのに、依存関係が気づかれないまま数か月も古い状態になります。
  • パッケージマネージャーレベルのクールダウンはセキュリティ修正をブロックします。Dependabot のクールダウンではブロックされません(アドバイザリーによる更新はクールダウンを回避します)。一方をもう一方に置き換えないでください。
  • 推移的依存関係にクールダウンが適用されることは実証されていません(npm では dependabot-core #14683 で問題が確認されています。pip/uv では未検証です)。推移的依存関係を実際にカバーするのは、手順 4 のロックファイル監査です。
  • ボットが作成した PR を過信しないでください:攻撃者は Dependabot のブランドを模倣し、axios のインシデントでは、CI がグリーンなら自動マージする設定によってマルウェアが取り込まれました。すべての PR と同様にレビューしてください。
  • Dependabot は SHA 固定されたアクションを通知しません(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 の違いなど)や、LLM の提案に含まれる幻覚によるパッケージ名(スロップスクワッティング)にも注意してください。uv add を実行する前に、pypi.org で正確な名前、リポジトリへのリンク、リリース履歴を確認してください。
  • 無料プランの対象範囲:依存関係グラフ、Dependabot alerts、セキュリティ更新はどこでも無料です。シークレットスキャンと 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 の場合はゼロ以外の終了コードを返します。

コメント