Movatterモバイル変換


[0]ホーム

URL:


Plan 9とGo言語のブログ

主にPlan 9やGo言語の日々気づいたことを書きます。

GitHubでサプライチェーン攻撃を防ぐ設定

ここ数ヶ月でサプライチェーン攻撃に関連していくつかベストプラクティスが出ていたので、GitHubリポジトリに適用しておいたほうがいいものをまとめた。

被害を受けないために

Dependabotにcooldownを設定する

過去のサプライチェーン攻撃では、ほとんどは問題のあるリリースが公開されてから数時間で発見されているので、自分のリポジトリが汚染されないためにリリースから一定期間はアップデートを保留するという手段が取られるようになったと記憶している。もともと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 を設定しているが、この他にもマイナーバージョンやパッチバージョンごとに期間を設定できる。

Actionsのバージョンをハッシュで強制する

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で検査を行う

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 }}"

ワークフローとして記述する内容については以下のドキュメントにまとまっている。

コード署名を必須にする

名前とアイコンだけでは不安があるのでコード署名も有効にできればより良いが、これは過去に記事を書いた。

blog.lufia.org

Immutable Releaseを設定する

いちどGitHub Releasesで公開したリリースを変更できなくするオプションも追加された。

これを有効にした状態でリリースを作成すると、リリースした内容を変更できなくなる

このオプションを使うには、リポジトリの設定でGeneral タブにあるRelease セクションでEnable Release Immutability を有効にする。Immutable Releasesを有効にした状態でリリースを作成すると、該当するリリースには鍵付きのアイコンにImmutable というラベルが付与される。

鍵アイコンにImmutableと文字が並んでいます

ただし不変となるのはコミットの内容とリリース成果物だけで、リリースのタイトル、リリースの説明文、プレリリース状態は依然として変更可能となっている。

Immutable Releasesでアセットを追加する

上記の通り、Immutable Releasesが有効になっていると、リリースにファイルのアップロードが行えなくなる。成果物をリリースに含めたい場合にどうするのかといえば、バージョンをいちどドラフトで作成して、成果物のアップロードが完了してから正式リリースに変更する手順を踏む必要がある。GitHub Releasesで各バージョンの状態は

  • Draft
  • Pre-release
  • Release

の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:書きかけのリリースを自動バックアップする機能と競合するためらしい

プロフィール
id:lufiabbid:lufiabbはてなブログPro

株式会社はてなMackerelチーム所属。主にPlan 9やGo言語の日々気づいたことを書きます。

検索

引用をストックしました

引用するにはまずログインしてください

引用をストックできませんでした。再度お試しください

限定公開記事のため引用できません。

読者です読者をやめる読者になる読者になる

[8]ページ先頭

©2009-2025 Movatter.jp