flowcheck について
flowcheckは、GitHub Actionsワークフローの過剰な権限、リスクのあるトリガー、シークレット露出を静的に監査します。リポジトリ管理者向けで、ファイル・ジョブ・行ごとの根拠と最小権限プランを示します。
主な機能
- 01ワークフローの権限とトリガーの監査
- 02ファイル・ジョブ・行ごとの検出結果
- 03ジョブごとの最小権限を推定
- 04強化した権限ブロックを出力
- 05実行せずに YAML を解析
活用シーン
- 01マージ前のワークフローセキュリティ確認
- 02特権コンテキストでのプルリクエストコード取得の検出
- 03より限定的なトークン権限の策定
- 04ネットワークなしでのリポジトリ監査
MCP 対応
MCP サーバーは、監査レポート用の `audit_workflows` と、ジョブ別権限プランおよび関連検出結果用の `harden_plan` を公開します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
2掲載時のツール一覧 · 2 日前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| path | string | はい | リポジトリのルート、.github/workflows ディレクトリ、または単一のワークフローファイル |
詳細
flowcheck
デフォルトの GitHub トークンは、リポジトリへの書き込みが可能です。ほとんどのワークフローは確認していません。
すべての GitHub Actions ワークフローは GITHUB_TOKEN を使って実行されます。レガシー設定で作成されたリポジトリでは、このトークンにほぼすべてへの書き込み権限が付与されており、permissions: ブロックのないワークフローは、リポジトリのデフォルト設定を引き継ぎます。さらに、特権コンテキスト内でプルリクエストのコードをチェックアウトするトリガーの構成、再利用可能なワークフローへのシークレットの一括受け渡し、PR の実行で書き込まれたキャッシュをリリースの実行で読み戻す構成が加わると、ワークフローファイル自体が攻撃対象になります。2025 年の tj-actions の侵害は、信頼されていたアクションがいかに素早く脅威に変わり得るかを示しました。また、「pwn request」に関する解説記事では、長年にわたり、pull_request_target で PR の head をチェックアウトすることの危険性が示されています。
flowcheck は、リポジトリ内のすべてのワークフローを監査して最小権限に関する問題を見つけ、ファイル、ジョブ、行ごとに根拠を示します。また、各ジョブのステップで実際に行われる処理から推定した、強化済みの権限ブロックを出力するので、そのまま貼り付けられます。
これが必要な理由
GitHub Actions は、昨年確認されたオープンソースのサプライチェーン攻撃対象のうち、npm に次ぐ 2 番目の規模です。問題は珍しいものではありません。たとえば、権限ブロックの欠落、write-all の指定、pull_request_target の下での ${{ github.event.pull_request.head.sha }} のチェックアウト、PR トリガーへのセルフホストランナーの応答などです。これらはすべて、何かを実行する前に YAML を静的に確認するだけで見つけられます。flowcheck は実際のパーサーで YAML を読み込み(アンカー、マージキー、ブロックスカラーにも対応)、スキャン対象のリポジトリ内のものは一切実行しません。また、MCP 経由でエージェントから呼び出せるため、手動での実行だけでなく、コントリビューションやリリースのワークフロー内でも監査できます。
関連ツールはそれぞれ異なる観点で確認します。actionpin はアクションの参照が SHA に固定されているかを確認します。flowcheck は権限とトリガーが最小権限になっているかを確認します。両者に共通のコードはありません。
検査項目
| ルール | 重大度 | 意味 |
|---|---|---|
FC-PERMS-WRITE-ALL | critical(トップレベル)、high(ジョブ) | permissions: write-all。トークンですべてのスコープに書き込みできます。 |
FC-PR-HEAD-CHECKOUT | critical | pull_request_target、workflow_run、または issue_comment トリガーと、ref が PR の head を指す checkout の組み合わせです。特権コンテキストで、信頼されていないコードを実行します。 |
FC-NO-TOP-PERMISSIONS | high または medium | トップレベルに permissions: ブロックがありません。ジョブはリポジトリのデフォルトトークンを継承します。多くのリポジトリでは、これは write-all です。 |
FC-JOB-GRANT-BROAD | medium(id-token の場合は high) | ジョブ(または継承元のトップレベルブロック)が、推定される必要性に照らして、そのジョブのどのステップにも必要のない書き込みスコープを付与しています。 |
FC-SECRETS-INHERIT | high または medium | 再利用可能なワークフロー呼び出しで secrets: inherit が指定され、リポジトリのすべてのシークレットが呼び出し先のワークフローに渡されます。 |
FC-SELF-HOSTED-PR | high | PR から到達可能なトリガーを持つワークフローで self-hosted ランナーが使われています。フォークのコードが、あなたのマシンとネットワーク上で実行されます。 |
FC-SECRETS-ON-PR | medium | pull_request ワークフロー内でシークレットが参照されています。同じリポジトリの PR ブランチは、マージ前にシークレットを使って実行されます。 |
FC-CACHE-POISON | medium | PR トリガー配下にあり、特権(書き込み)コンシューマーも持つワークフロー内のキャッシュステップです。汚染されたキャッシュエントリーが、後続の特権実行内でコードを実行する可能性があります。 |
FC-ARTIFACT-WORKSPACE | medium | actions/upload-artifact がワークスペース全体(path: .、**、または path の指定なし)をアップロードしています。これには通常、.git、設定ファイル、流出したシークレット情報が含まれます。 |
FC-PERMS-READ-ALL | low | 明示的なスコープ一覧の代わりに permissions: read-all が指定されています。 |
FC-NO-TIMEOUT | low | timeout-minutes のないジョブです。プラットフォームのデフォルトは 360 分です。 |
FC-NO-CONCURRENCY | low | デプロイに関係するジョブ(リリース、公開、イメージのプッシュ、または environment)に、ジョブまたはワークフローレベルの同時実行ガードがありません。 |
FC-DISPATCH-INPUT-INJECTION | low | workflow_dispatch の入力値が run ステップに直接埋め込まれ、自由入力テキストがシェルとして扱われます。 |
FC-PARSE-ERROR | medium | ワークフロー YAML を正しく解析できません。 |
判定ルール:
- EXPOSED:critical または high の検出結果が 1 件以上あります。終了コードは 1 です。
- REVIEW:medium または low の検出結果のみです。終了コードは 1 です。
- HARDENED:検出結果はありません。終了コードは 0 です。
- 使用方法の誤りはコード 2 で終了します。出力パイプが早期に閉じられた場合、プロセスは 0 ではなく 141 で終了します。
強化プラン
flowcheck は、すべてのジョブについて、各ステップに必要な最小限の権限を推定します。
| ステップの形式 | 推定される権限 |
|---|---|
actions/checkout | contents: read |
リリースの作成(gh release create、softprops/action-gh-release) | contents: write |
イメージのプッシュ(push を使った docker/build-push-action、docker push、buildx --push) | packages: write |
PR への書き込み(gh pr create、gh pr comment、ラベラー、stale) | pull-requests: write |
Issue への書き込み(gh issue comment など) | issues: write |
Pages のデプロイ(actions/deploy-pages) | pages: write、id-token: write |
| OIDC サインイン(AWS、Azure、Google の認証アクション、スクリプトでの明示的な OIDC 使用) | id-token: write |
ビルドの来歴情報(actions/attest-build-provenance) | attestations: write、id-token: write |
| トークンを一切使用しない場合 | permissions: {} |
audit は検出結果と並べてプランを出力します。harden はジョブごとのブロックとトップレベルの統合ブロックを出力します。ファイルには何も書き込まれません。プランが出力されるので、自分で貼り付けてください。
使用方法
CLI
# Audit the current repo
npx @reneturcios/flowcheck audit
# Audit another path, machine readable
npx @reneturcios/flowcheck audit ~/src/my-repo --json
# Just the hardening plan
npx @reneturcios/flowcheck harden ~/src/my-repo
出力例:
flowcheck audit .: EXPOSED
workflows: 2, jobs: 3, findings: 2 (critical: 1, high: 1, medium: 0, low: 0)
[CRITICAL] .github/workflows/pr.yml:14 FC-PR-HEAD-CHECKOUT (job inspect) Privileged trigger context (pull_request_target) combined with a checkout of the PR head (...)
[HIGH] .github/workflows/pr.yml:1 FC-NO-TOP-PERMISSIONS No top-level permissions block. ...
EXPOSED: at least one critical or high finding. ...
監査に認証情報やネットワークは不要です。対象数の上限は明示され、通知なしで適用されることはありません。1 回の実行につきワークフローファイルは最大 500 個、ファイルサイズは最大 2 MiB です。上限に達した場合は、レポートの caps フィールドと注記で、上限に達したこととスキャンされなかった対象を示します。
MCP サーバー
MCP クライアントの設定に追加します。
{
"mcpServers": {
"flowcheck": {
"command": "npx",
"args": ["-y", "@reneturcios/flowcheck", "mcp"]
}
}
}
ツール:audit_workflows(path) は監査レポート全体を JSON で返します。harden_plan(path) はジョブごとの強化された権限ブロック、トップレベルの統合ブロック、およびそれらが対応する検出結果を返します。
平易に説明した制限事項
- 権限の推定はヒューリスティックです。上記の表にあるステップの形式に加え、一般的な
ghCLI とスクリプトのパターンを認識します。未知のサードパーティ製アクションは、プランが示すより多く(または少なく)の権限を必要とする場合があります。プランは人が確認するための出発点であり、証明ではありません。 - 広範な権限付与に関する検出結果は、処理内容が見えないコンシューマーを考慮して調整されています。ジョブに、トークンの使用状況をワークフローファイルから確認できないステップ(未知のサードパーティ製アクション、ローカルのコンポジットアクション、またはリポジトリ内のファイルに処理を委譲することが多い任意の JavaScript を実行する
actions/github-scriptステップ)が含まれる場合、検出結果は中または高ではなく、その注意書きを添えて低い重大度で報告されます。flowcheck は v0.1.0 では、ローカルのコンポジットアクションファイルや、ステップから委譲されるスクリプトを追跡しません。 - PR のヘッドをチェックアウトするルールでは、ヘッド(
pull_request.head、head_ref、workflow_run.head)を指す明示的な ref 式が必要です。pull_request_targetのもとで ref を指定せずにチェックアウトするとベースブランチがチェックアウトされるため、安全な形式として検出されません。環境変数や出力を組み合わせて間接的にヘッドをチェックアウトするケースは追跡されません。 - セルフホストの検出では、
runs-onにリテラルのself-hostedラベルがあるかを確認します。このラベルを含まない名前のランナーグループは認識されません。 - 再利用可能なワークフローのジョブは呼び出し元の記述だけをもとにプランが作成されます。呼び出されるワークフロー自体のステップは、別途監査対象となります。
- マトリックスによって生成されるジョブは、マトリックスの組み合わせごとではなく、記述どおりに一度だけ監査されます。
- シークレットのルールは
pull_request配下の参照を数えますが、特定のシークレットが特定のステップに渡されることの証明は試みません。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。