ここ数ヶ月でサプライチェーン攻撃に関連していくつかベストプラクティスが出ていたので、GitHubのリポジトリに適用しておいたほうがいいものをまとめた。
過去のサプライチェーン攻撃では、ほとんどは問題のあるリリースが公開されてから数時間で発見されているので、自分のリポジトリが汚染されないためにリリースから一定期間はアップデートを保留するという手段が取られるようになったと記憶している。もともとRenovateにはminimumReleaseAge オプションがあったのだが、Dependabotでもcooldown オプションが使えるので設定する。
このオプションを設定しても、上の記事中に
Key benefits
- Stay responsive to critical security patches.
とあるように脆弱性の修正はcooldown の設定よりも優先してアップデート対象となるらしいので、ある程度日数を開けても問題ないと思う。設定例は以下の通り。
version:2updates:-package-ecosystem: github-actionsdirectory: /schedule:interval: weeklycooldown:default-days:5
上記では、サプライチェーン攻撃に関していえばパッチバージョンだから安全という訳でもないのでdefault-days を設定しているが、この他にもマイナーバージョンやパッチバージョンごとに期間を設定できる。
GitHub ActionsではGitのタグを使ってバージョンを特定しているので、もともと安全だったタグが攻撃者によって悪意のあるコミットに向けられてしまって汚染されることがある。こういった攻撃を防ぐため、GitHubは公式にSecure use reference#Using third-party actionsで
You can help mitigate this risk by following these good practices:
- Pin actions to a full-length commit SHA
のようにハッシュによるバージョン参照を推奨していたのだが、2025年8月にハッシュで参照することを強制するRequire actions to be pinned to a full-length commit SHA オプションが追加された。
公式がハッシュによる参照を推奨しているので上記のオプションも有効にするといいと思うけれど、このオプションはワークフローが依存するすべてのアクションでハッシュ指定を強制するので、外部のアクションにタグ指定がひとつでもあるとエラーになる。例えば筆者は一部のワークフローでgovulncheck-actionを使っているのだけど、2025年10月時点ではgovulncheck-action にはタグを使ってバージョンを参照するコードが含まれているので、上記オプションを有効にするとエラーとなってワークフローを実行できないので状況を確認しつつ有効にしていくといい。
CodeQLはGitHubが公式に提供するコードスキャナで、2025年10月時点ではCodeQLの設定は以下2通りの方法がある。
CodeQLはリポジトリの設定画面からAdvanced Security タブのCode Scanning セクションで有効にできる。2025年10月時点では、上記でRequire actions to be pinned to a full-length commit SHA オプションを設定していると
Code scanning withGitHub Actions is not available for this repository
と警告が出てセットアップを行えない状態となるが、その状態でも自分でワークフローを記述すれば高度なセットアップとしてCodeQLが動作する。高度なセットアップでは以下のようなGitHub Actionsのワークフローとして記述する。
## この内容はブログ記事に掲載するため簡略化しているので、リポジトリの設定から## Advanced Security/Code Scanningセクションで「Advanced」を選んで出てくるテンプレートを参照してください。name:"CodeQL Advanced"on:push:branches:-mainpull_request:branches:-mainschedule:-cron:'17 2 * * 6'jobs:analyze:name: Analyze (${{ matrix.language }})runs-on: ubuntu-latestpermissions:security-events: writepackages: readactions: readcontents: readstrategy:fail-fast:falsematrix:include:-language: actionsbuild-mode: none-language: gobuild-mode: autobuildsteps:-name: Checkout repositoryuses: actions/checkout@v4-name: Initialize CodeQLuses: github/codeql-action/init@v3with:languages: ${{ matrix.language }}build-mode: ${{ matrix.build-mode }}-name: Perform CodeQL Analysisuses: github/codeql-action/analyze@v3with:category:"/language:${{ matrix.language }}"
ワークフローとして記述する内容については以下のドキュメントにまとまっている。
名前とアイコンだけでは不安があるのでコード署名も有効にできればより良いが、これは過去に記事を書いた。
いちどGitHub Releasesで公開したリリースを変更できなくするオプションも追加された。
これを有効にした状態でリリースを作成すると、リリースした内容を変更できなくなる
このオプションを使うには、リポジトリの設定でGeneral タブにあるRelease セクションでEnable Release Immutability を有効にする。Immutable Releasesを有効にした状態でリリースを作成すると、該当するリリースには鍵付きのアイコンにImmutable というラベルが付与される。

ただし不変となるのはコミットの内容とリリース成果物だけで、リリースのタイトル、リリースの説明文、プレリリース状態は依然として変更可能となっている。
上記の通り、Immutable Releasesが有効になっていると、リリースにファイルのアップロードが行えなくなる。成果物をリリースに含めたい場合にどうするのかといえば、バージョンをいちどドラフトで作成して、成果物のアップロードが完了してから正式リリースに変更する手順を踏む必要がある。GitHub Releasesで各バージョンの状態は
の3つで推移するので、手動でリリース成果物を追加した後でPre-release またはRelease に変更すればいい。
手動またはGitHubCLI等で人間がアップロードする場合はそれでいいのだけれども、GitHub Actionsのワークフローを使って成果物のアップロードを行っていた場合は問題がある。具体的には以下のワークフローについて
on:release:types:-published # リリースが公開されたときにワークフローをトリガーするjobs:build:runs-on: ubuntu-lateststeps:-uses: actions/checkout@v5-run: make zip-uses: actions/upload-artifact@v4with:name: artifactspath:"*.zip"deploy:needs: buildpermissions:contents: writeruns-on: ubuntu-lateststeps:-uses: actions/checkout@v5-uses: actions/download-artifact@v5with:path: artifactsmerge-multiple:true-name: releaserun: | gh release upload"$TAG" artifacts/*.zipenv:TAG: ${{ github.ref_name }}GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
このとき、Immutable Releasesが有効になっているとgh release upload によるアップロードが行えなくなる。上にも書いたようにドラフトであれば成果物の追加が行えるけれども、ドラフトの状態でワークフローをトリガーするイベント が、少なくとも今の時点では存在しない*1。
ではどうするのかというと、公式ドキュメントにUsing immutable releases and tags to manage your action's releasesがあって、このドキュメントではGitのタグとして作る方法が紹介されていたのでこの方法でリリースを行うことにした。ワークフローの差分は以下の通り。
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.ymlindex ef97f43..c1db329 100644--- a/.github/workflows/deploy.yml+++ b/.github/workflows/deploy.yml@@ -1,9 +1,9 @@ name: Release on:- release:- types:- - published+ push:+ tags:+ - v[0-9]+.[0-9]+** jobs: build:@@ -47,7 +46,10 @@ jobs: merge-multiple: true - name: release run: |- gh release upload "$TAG" artifacts/*.zip+ gh release create "$TAG" \+ --title="$TAG" \+ --generate-notes \+ --draft artifacts/*.zip env: TAG: ${{ github.ref_name }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
リリースを行いたいときGitのタグをプッシュすれば、ワークフローによってドラフトのリリースが作られる。このとき、上記ワークフローではリリースノート生成と成果物のアップロードまで行うように変更しているが、リリースノートの内容は後からGitHubのUIで変更できるし、リリースと関連付けられていないタグなら削除できるので、タグ付けを間違えた場合はドラフトリリースとGitのタグそのものを削除してやり直せばいい。
ただ、誤って先にGitHubのUIでリリースとして作ってしまった場合は(もう消せないしアップロードもできないので)新しくタグを作るしかなくなってしまうけれども、Immutable Releasesを使わないよりはメリットが大きいだろうから諦める。
*1:書きかけのリリースを自動バックアップする機能と競合するためらしい
引用をストックしました
引用するにはまずログインしてください
引用をストックできませんでした。再度お試しください
限定公開記事のため引用できません。