tea-e7n.dev

GitHub Actions workflowの依存をlockする、gh actions-lock

最近GitHub Actionsのサプライチェーン攻撃をよく耳にします。

workflowの依存を{package}@{version}の形式で指定して利用しているとき、そのタグが別のcommitを指すように動かされてしまい、なにもしていないのに脅威を踏んでしまうというのが、そのざっくりとした概要となります。

従来、この問題については、外部パッケージを利用するときにバージョンではなくコミットハッシュを直に参照することで、対応してきました。

これ自体が問題というわけではないのですが、せっかくバージョンごとにリリースされているのに、その恩恵を受けられず、毎回コミットハッシュを探してコピペする必要があるという点で、少し面倒な構造になっていました。

しかしそんな中登場したのが、今回紹介するgh actions-lockです。

まあ名前のまんまではあるんですが、GitHub Actionsのworkflowの依存をlockすることができます。

具体的な使いかたを見ていきます。

環境

  • macOS 26.6.2
  • gh version 2.102.0

インストール

インストール手順があるので、その通りに実行します。

❯ gh extension install github/gh-actions-lock

次のコマンドが通ればインストール完了です。

❯ gh actions-lock -v
actions-lock version v0.2.0

使ってみる

一旦無邪気に実行してみます。GitHub Actionsのworkflowが定義されているリポジトリに移動して、次のコマンドを実行します。

❯ gh actions-lock

✓ Pinned 4 actions (+ 1 transitive) across 2 workflows
...

実行すると、workflowのusesが、その時点で解決された具体的なバージョンへ書き換えられます。たとえばdeploy-action@v3のような指定は、指しているcommitはそのままで、deploy-action@v3.1.0のように具体化されます。あわせて.github/workflows/actions.lockというlockファイルが作成されます。

actions.lockはよくあるlockファイルと同様、バージョンと、対応するcommit hashが記録されています。

actions.lockにワークフローが登録されていると、そのジョブはタグが今指しているcommitではなく、lockに記録されたcommitを実行します。依存がlockに載っていない場合は、ジョブは実行されずに止まります。

gh actions-lock –verify

gh actions-lockコマンドは--verifyというオプションを用意しています。

これは、ファイルを書き換えずに、生成済みのactions.lockが今の参照と合っているかを確認してくれます。mainやv4のようにブランチや部分バージョンでlockしている場合は、記録したcommitがまだそのrefの履歴に残っているかも見ます。

検証に失敗したときは、lockが古くなっていることを教えてくれます。

このコマンドは、CIとして動かして定期的に結果を確認できると良さそうです。

Organizationでの設定

例えば新規のworkflowを追加したときに、ついlockするのを忘れてしまい、actions.lockの恩恵を受けられないという場面が考えられます。 最悪の場合に、その処理漏れによってセキュリティインシデントに繋がってしまうことも考えられます。

そのようなことを引き起こさないために、Require lockfileというポリシーで、依存がlockされていないworkflowの実行を止められるようになっています。

Organizationの場合、Organization > Settings > Actions > Policiesから設定可能となっていることを確認できました。(Repository単位でも設定可)

まとめ

特別な理由がない限り、GitHub Actionsを利用している環境では導入しておいたほうがいい仕組みだと思いました。

図を拡大