pinact で GitHub Actions のバージョンを SHA pinning しよう

pinact で GitHub Actions のバージョンを SHA pinning しよう

サードパーティ Action の乗っ取りによるサプライチェーン攻撃 #

この GitHub Actions の定義にはセキュリティの脆弱性があります。

name: test
on: pull_request
jobs:
  my-job:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v6

actions/checkout@v6 のところです。例えばいま v6 の最新版が v6.1.2 だとします。

actions/checkout の開発権限が乗っ取りに合い、コードに悪意のあるコードが混入し、v6.1.3 としてリリースされたとします。

v6 という指定は、v6.1.3 が公開された時点で v6.1.3 を参照します。その結果、あなたの GitHub Actions の定義は悪意のあるコードを実行してしまいます。

では actions/[email protected] と指定しておけば安全かというとそうでもありません。タグは付け替えが可能なため、悪意のある開発者は悪意のあるコードを含むコミットに対し v6.1.2 のタグを付け、既存のタグを上書きすることで、やはりあなたの定義は悪意のあるコードを実行してしまいます。

これはいわゆるサプライチェーン攻撃の一種です。

GitHub Actions におけるこの脆弱性は SHA ピンニング(SHA pinning)で回避できます。SHA ピンニングとは、GitHub Actions の定義において、タグではなくコミット SHA を指定することです。

具体的には以下のように定義します。

name: test
on: pull_request
jobs:
  my-job:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10

df4cb1c069e1874edd31b4311f1884172cec0e10 とは actions/checkoutv6.0.0 のコミットハッシュです。結果的には actions/[email protected] と同じ意味になります。

ただし、タグと異なりコミットハッシュは後からの付け替えができません。そのため、悪意のある開発者が悪意のあるコードを含んだバージョンを公開したとしても、あなたの定義は悪意のあるコードを実行することはありません。

Action の呼び出しは SHA pinning を推奨 #

すべて SHA pinning で書くことが推奨です。

しかし、手作業で SHA pinning するのは大変です。そこで pinact というツールを使うと便利です。

CLI ツールとなっており、実行することで GitHub Actions のすべての Action のバージョンを SHA pinning してくれます。

まずはなにかしらの方法で pinact をインストールします。Homebrew でインストールする場合は以下のコマンドです。

brew install pinact

そうすると pinact コマンドが使えるようになります。pinact --help でヘルプが表示されます。

pinact --help

NAME:
   pinact - Pin GitHub Actions versions. https://github.com/suzuki-shunsuke/pinact

USAGE:
   pinact [global options] [command [command options]]

VERSION:
   4.1.0

COMMANDS:
   init        Create a pinact configuration file if it doesn't exist
   run         Pin GitHub Actions versions
   migrate     Migrate .pinact.yaml
   token       Manage GitHub Access token
   version     Show version
   help, h     Shows a list of commands or help for one command
   completion  Output shell completion script for bash, zsh, fish, or Powershell

GLOBAL OPTIONS:
   --log-level string          log level [$PINACT_LOG_LEVEL]
   --config string, -c string  configuration file path [$PINACT_CONFIG]
   --help, -h                  show help
   --version, -v               print the version

さて SHA pinning ですが、pinact run を実行するだけです。

pinact run

実行後、以下のように GitHub Actions の定義が SHA pinning されます。

.github/workflows/my-ci.yml:31
-         uses: actions/checkout@v6
+         uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
.github/workflows/my-ci.yml:34
-         uses: actions/setup-node@v6
+         uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0

その他参考 #