mcpField
A
actionpin

actionpin

ローカル
github.com/CloudCorpRecordsセキュリティ01 日前に更新

actionpin について

actionpinは、GitHub Actionsのワークフローと複合アクション定義を監査し、可変参照をコミットSHAに固定する計画を作成します。証拠に基づくサプライチェーン検査を行うメンテナーやエージェント向けで、CLIとMCPインターフェースを備えています。

主な機能

  1. 01アクション参照を固定状態で分類
  2. 02ワークフロー監査の判定を報告
  3. 03SHA固定計画を作成
  4. 04修正モードで解決可能な参照を変更
  5. 05対象の複合アクション定義を検査

活用シーン

  1. 01リポジトリのActionsサプライチェーンリスク確認
  2. 02リリース前のワークフローアクション確認
  3. 03ファイルを変更せずにSHA変更をプレビュー

MCP 対応

MCPサーバーは、リポジトリ監査用の`audit_workflows`と、ファイルを変更せずにSHA固定計画を返す`pin_plan`を提供します。記載された`npx`設定によりMCPクライアントから実行できます。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"cloudcorprecords-actionpin": {
"command": "npx",
"args": [
"-y",
"@reneturcios/actionpin"
]
}
}
}
起動コマンドnpx -y @reneturcios/actionpin

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
npm@reneturcios/actionpin0.1.8
ocighcr.io/cloudcorprecords/actionpin:0.1.8

ツール

2

掲載時のツール一覧 · 2 日前に更新

パラメーター型必須説明
pathstringはいリポジトリのルート、.github/workflows ディレクトリ、または単一のワークフローファイル

詳細

actionpin

バージョンタグは誰でも変更できますが、コミット SHA は変更できません。

GitHub Actions は実行可能なサプライチェーンです。ワークフローに uses: actions/checkout@v4 と書かれている場合、そのタグは変更される可能性があります。サードパーティアクションのタグが侵害されたコミットに変更されると、そのタグを信頼するすべてのワークフローが、そのワークフローのトークンを使って新しいコードを実行します。40 文字の完全なコミット SHA に固定するのが標準的な防御策ですが、手作業で各ワークフローに適用するのは面倒で間違いやすいため、ほとんどの人は一貫して実施できていません。

actionpin はリポジトリ内のすべてのワークフローを監査し、どのアクションが固定済みで、どれが未固定かを正確に報告します。また、未固定のアクションを SHA に書き換えることもできます。その際、元のタグをコメントとして残すため、固定後も読みやすさを保てます。

なぜ必要なのか

GitHub Actions は、昨年確認されたオープンソースのサプライチェーン攻撃対象のうち、npm に次いで 2 番目に大きな対象です。メンテナーのアカウントやアクションのタグが乗っ取られた事例があり、変更可能なタグを使うと、今日 CI が実行するコードがレビュー済みのコードと同じである保証はありません。対策は明確でシンプルです。SHA に固定します。actionpin を使えば、このシンプルな対策を 1 つのコマンドで実施できます。また、MCP 経由でエージェントから呼び出せるため、手作業だけでなく、コントリビューションやリリースのワークフロー内でも監査を実行できます。

チェック対象

.github/workflows/*.yml および *.yaml 内のすべての uses: 行を対象とします。

分類意味
PINNED参照先が 40 文字の完全なコミット SHA、またはコンテナイメージの完全な sha256/sha512 コンテンツダイジェストです
MUTABLE参照先が v4 や v4.2.1 などのバージョンタグです。タグは変更される可能性があります
BRANCH参照先が main、master、HEAD などのブランチです。仕様上、変更されます
LOCAL./local/action などのローカルパスです。書き換えは行いません

所有者の種類:actions または github が所有するアクションは official、それ以外は third-party、docker:// コンテナアクションは docker、ローカルパスは local です。

判定ルール:

  • PINNED:ローカル以外のすべてのアクションが完全な SHA に固定されています。終了コードは 0 です。
  • EXPOSED:少なくとも 1 つのサードパーティまたはコンテナアクションが、変更可能なタグまたはブランチを使用しています。終了コードは 1 です。
  • PARTIAL:未固定なのは公式アクションだけです。終了コードは 1 です。
  • 使用方法のエラー:終了コードは 2 です。

修正モードでは、GitHub API を通じてタグまたはブランチをコミット SHA に解決し、行を owner/repo@<sha> # <original ref> に書き換えます。インデントやその他の内容は維持されます。ファイルは行単位で編集され、YAML の解析や再出力は行われないため、書式はそのまま保たれます。参照先を解決できない場合、その行は変更されず、失敗が報告されます。Docker イメージの参照先は報告されますが、書き換えは行われません。これらはダイジェストに固定してください。

使い方

CLI
# Audit the current repo
npx @reneturcios/actionpin audit

# Audit another path, machine readable
npx @reneturcios/actionpin audit ~/src/my-repo --json

# Preview the pinning plan without writing
npx @reneturcios/actionpin fix --dry-run

# Pin everything resolvable, in place
npx @reneturcios/actionpin fix

出力例:

actionpin audit .: EXPOSED
  workflows: 2, actions: 6, pinned: 1, mutable: 4, branch: 1, local: 0
  [PINNED] .github/workflows/ci.yml:12 actions/checkout@0123456789abcdef0123456789abcdef01234567 (official)
  [MUTABLE] .github/workflows/ci.yml:13 actions/setup-node@v4 (official)
  [MUTABLE] .github/workflows/publish.yml:20 docker/build-push-action@v6 (third-party)
EXPOSED: at least one third-party or container action uses a mutable tag or branch ref.

修正モードで GitHub API の認証済みレート制限を引き上げるには、GITHUB_TOKEN を設定してください。監査には認証情報もネットワークも必要ありません。

MCP サーバー

MCP クライアントの設定に追加します。

{
  "mcpServers": {
    "actionpin": {
      "command": "npx",
      "args": ["-y", "@reneturcios/actionpin", "mcp"]
    }
  }
}

ツール:

  • audit_workflows:リポジトリのパスを監査し、すべてのアクションについて分類、所有者の種類、ファイル、行番号と、判定結果を返します。
  • pin_plan:ファイルを書き換えずに、指定したパスの完全な SHA 固定計画を返します。
Docker
docker run -i ghcr.io/cloudcorprecords/actionpin mcp
docker run --rm -v "$PWD:/work" -w /work ghcr.io/cloudcorprecords/actionpin audit .

制限事項(堅牢性テストで固定済み)

これらの動作は意図的なもので、テスト済みです。緑色のレポートが誤解されないよう、明確に記載しています。

  • 対象はワークフローファイルとリポジトリ内のコンポジットアクションです。 ディレクトリ監査では .github/workflows/*.yml と *.yaml をスキャンし、スキャン対象リポジトリ内にあるアクション定義もスキャンします。具体的には、ルート階層の action.yml または action.yaml(スキャン対象リポジトリ自身の公開アクション定義です。ワークフローから参照されているかどうかにかかわらずスキャンされます。アクションを提供するリポジトリでは、これが通常の構成です)、.github/actions/ 以下のすべての action.yml と action.yaml、およびワークフローが ./ で始まる uses パスで参照するローカルアクションディレクトリです。これらの内部ステップはワークフローステップと同様に一覧化、分類され、コンポジットアクション参照としてフラグが付けられ、同じ方法で判定を左右します。ルートアクションのステップがリポジトリ自身のアクション(./ または公開名経由)を参照している場合、そのアクションは一度だけスキャンされます。自己参照による再帰や二重カウントは発生しません。レポートにはスキャンしたコンポジットファイルの数と、リポジトリ内の別の場所に見つかったもののスキャンされなかったアクションファイル(ルートアクションファイルではなく、.github/actions の外にあり、ワークフローからも参照されていないもの)の名前が記載されるため、監査範囲を超えるカバレッジがあるかのように示されることはありません。action.yml のファイルパスを直接渡した場合も、ほかのファイルと同様に解析されます。ジョブレベルの uses: 行(再利用可能なワークフローの呼び出し)も対象であり、ステップレベルのものと同様に監査され、ピン留めされます。
  • 不正なプレフィックスを持つローカルパスもローカルとして扱われ、誤記はそのまま表示されます。 $/.github/actions/issues-helper のような uses 値(実在のリポジトリで使われている、./ プレフィックスのドットにあたる部分に余計な文字が入ったもの)はリモートリポジトリを指さないため、LOCAL と分類され、修正モードで GitHub API を使って解決されることはありません。検出結果には、そのプレフィックスが有効なリモート参照ではなく、ローカルパスの誤記のように見えるという注記が含まれます。ピン留めに関するリスクではないものの、対象リポジトリに実際の不具合があるためです。
  • 動的な値は推測せず、スキップします。 GitHub 式(${{ matrix.action }}、actions/checkout@${{ inputs.ref }} など)を含む uses: 値は実行時に決まるため、静的に分類できません。actionpin はアクションや判定をでっち上げず、対象を完全にスキップします。ワークフローがアクションを動的に組み立てる場合は、マトリックスや入力の値自体を監査してください。
  • 短い SHA はピン留め済みとは見なされません。 PINNED と見なされるのは、完全な 40 文字の SHA、または docker:// イメージの完全な sha256 もしくは sha512 ダイジェストのみです。abc1234 のような短い SHA は BRANCH 区分で報告され、短いプレフィックスは安定したピン留めではないため、判定は失敗します。
  • コンテナタグはピン留め済みとは見なされません。 docker:// イメージでは、完全なコンテンツダイジェストのみが有効です。40 桁の 16 進数で表記されたタグであっても、再プッシュできるためタグのままであり、切り詰められたダイジェストや 16 進数以外を含むダイジェストもダイジェストとして無効です。どちらも MUTABLE です。
  • YAML のアンカーとエイリアスはファイル内で解決されます。 GitHub Actions は 2025 年 9 月からこれらをサポートしています。アンカー付きの uses: 値はその値自体で分類され、エイリアス行(uses: *name またはステップエイリアス - *name)はアンカーの分類を継承して viaAlias フラグが付きます。GitHub の仕様と同様に、アンカーは同じファイル内で使用箇所より前に定義されている必要があります。修正モードではアンカーの定義行をピン留めし、エイリアス行を書き換えることはありません。
  • スラッシュを含む参照(release/v1、feature/new-thing)は、移動する参照として BRANCH 区分で報告されます。修正モードでは、スラッシュを保持したまま git-ref API を通じて解決します。
  • 行単位の解析です。 1 行にまとめたフロー形式の YAML(例:steps: [{ uses: actions/checkout@v4 }])は検出されず、コメントアウトされた uses: 行は無視されます。
  • Docker 参照は報告されますが、書き換えは行いません。 コンテナイメージは手動でダイジェストによりピン留めしてください。修正モードでは docker:// 行を変更せず、その旨をプランに記載します。
  • 対象が空の場合はその旨を示します。 監査対象パスの下にワークフローもアクション定義も見つからない場合、レポートには監査対象がなかったことを示す通常の注記が含まれます。判定はアクション 0 件に基づいて計算されるため、そのパスに問題がないことを示すものではありません。監査可能な対象がルートアクション定義だけのリポジトリでは、その定義が監査され、対象が空であるという注記は付きません。
  • 存在しない対象や型が誤っている対象は使用エラーとなり、判定は出力されません。 パスが存在しない場合は stderr にエラーを出力して終了コード 2 で終了し、レポートは出力しません。hookcheck や injectcheck と同様に、CI に誤ったパスを設定した場合、何もない状態で成功扱いされずに失敗します。単一ファイルを渡した場合、監査対象となるのは .yml または .yaml ファイルのみです。それ以外の通常ファイル(package.json や README など)を渡すと、ワークフローとして扱われるのではなく、使用エラーとして終了コード 2 で終了します。ファイルでもディレクトリでもない対象も使用エラーです。
  • 通常ファイル以外は決して開きません。 検出時に各候補を開く前にファイル情報を取得し、通常ファイル以外はスキップします。そのため、FIFO(名前付きパイプ)、ソケット、デバイスがワークフローやアクションファイルのパスに置かれていても、監査が停止したりブロックしたりすることはありません。周囲にある通常ファイルは通常どおり監査されます。
  • パイプ出力は全体が渡されるか、実行が失敗します。 レポートの出力にはフラッシュに対応した出力経路を使うため、エージェント、スクリプト、CI が利用する際に、サイズを問わずレポート全体をパイプ経由で受け取れます。レポートの出力前に読み取り側がパイプを閉じた場合、actionpin は終了コード 141(シェルから見た SIGPIPE 相当)で終了し、受け取られていない出力を成功扱いしません。Round 1 の実リポジトリ検証で、終了コードが成功のままちょうど 65,536 バイトで出力が黙って切り詰められる問題が見つかったため、0.1.2 で修正しました。

ツールキット

actionpin は、同じ作者による小規模で単一目的の開発者向けツール群の一つです。すべて同じ方法で構築されており、1 つのバイナリで CLI と MCP サーバーを提供し、証拠に基づく決定論的なチェックを行い、回答を捏造しません。

  • greenlight:オープンソースへのコントリビューションの事前チェックを行います。この Issue は実際に取り込める状態ですか?
  • shipcheck:リリースが git、npm、MCP Registry、GHCR で実際に公開されたことを検証します。
  • hookcheck:リポジトリ内の自動実行フックを監査し、永続化に関するリスクを調べます。

開発

npm install
npm run build
npm test

テストは注入された fetch 関数を使用してフィクスチャ上で実行されます。ネットワークにアクセスするテストはありません。

ライセンス

MIT

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。