🐧

GitHub の Immutable Releases を有効にしてセキュリティインシデントを防ごう

に公開

先日 (2025-08-26) public preview になった GitHub の Immutable Releases を紹介します。
このセキュリティ的に極めて重要な機能が普及してほしいという気持ちで書くことにしました。
まだ public preview なので早いかもですが、 GitHub でソフトウェアをバージョニングして公開している方は是非全リポジトリで有効にしましょう。

https://github.blog/changelog/2025-08-26-releases-now-support-immutability-in-public-preview/

https://github.com/orgs/community/discussions/171210

Immutable Releases は GitHub Tag や Release, Release assets を後から変更できないようにする機能です。
tag や assets が改竄されることによるセキュリティインシデントを防ぐことができます。

最初に注意点を挙げておきます:

  • draft release は mutable
    • draft でない release には後から asset を upload できなくなるため、 API で release と asset を作成する場合、 draft release を作って asset を upload してから draft を解除する必要がある
  • Release ごと削除することはできる
    • ただし、同じ tag に再び Release を作成することはできない
  • 一度 immutable になった release はリポジトリの設定で Immutable Release を無効化しても immutable なまま
  • 過去の Release は mutable のまま
  • Immutable な tag も削除できる
    • ただし、同じ名前の tag を再作成はできない
  • Release に紐づかない tag は immutable ではない
    • 削除して同名の tag を作成できる
    • GitHub Actions の v1 みたいな mutable な tag も問題なく更新できる
      • その場合 v1 みたいな tag が immutable release と同じ SHA を指す保証はないので、改竄されるリスクはある
        • tag protection rule で改竄を防ぐことは頑張れば可能かもしれないが、利用者側としてそもそも v1 みたいな tag を参照しないほうが無難では

リポジトリ及び Organization の設定で簡単に有効化できます。

Repository の設定: General

Organization の設定: Repository > General

Organization 配下のリポジトリはまとめて有効化できて便利ですが、残念ながら User には Organization の設定のようなものはないので、 User 配下のリポジトリは一つ一つ有効化していく必要があります。
また今のところ API はないので手動でポチポチする必要があります。
将来的に API が公開されるようです。

設定を有効化すると、それ以降に作成された release と関連する tag は Immutable になります。
Web UI から Release を作成しようとすると pop up が出るようになります。

Confirm to publish
As an immutable release, you will only be able to edit the release title and notes after publishing.
You can save a draft of this release if you're not ready to publish.

作成された Release を見ると UI から immutable であることがわかります。

有効化前に作ったものは mutable のままです。
なので今後リリースを作成する前には有効化しておきましょう。
有効化したらリリースを 1 つ作ってそれを使うように案内すると安全でしょう。

Immutable Release の asset は追加・修正・削除ができなくなります。
Release title と note は変更できます。
Release を編集しようとしても asset は変更できないことがわかります。

As an immutable release, only release title and notes can be updated after publishing. Learn more about immutable releases

Immutable Release に API で asset を upload しようとすると失敗します。

HTTP 422: Cannot upload assets to an immutable release. (https://uploads.github.com/repos/szksh-lab-2/test-github-action/releases/244716146/assets?label=&name=README.md)

Immutable な tag の削除はできますが、同じ名前の tag は作成できません。
Immutable Release を作成した後に release, tag を削除し、別の commit に同じ名前の tag を作成して push しようとしたら失敗しました。
エラーメッセージからは Immutable Release が原因であることは読み取れませんが、 Immutable Release が原因なはずだと思います。

 ! [remote rejected] v0.11.2 -> v0.11.2 (push declined due to repository rule violations)
error: failed to push some refs to 'https://github.com/szksh-lab-2/test-github-action'

なお、 Release に紐づかない tag は immutable ではなく、削除して同名の tag を作成することができます。

Release は削除できますが、同じ tag を使って Release の再作成はできません。
Web UI から試したところ、以下のようなエラーが発生しました。

We weren’t able to create the release for you. Make sure you have a valid tag.

There was an error creating your Release: tag name was used by an immutable release.

ただし、 Draft Release の asset は追加・修正・削除ができます。

ところで、 GitHub REST API の Create Release API では asset の upload ができません。
つまり API で asset を upload しようと思ったら、 Release を作ってから asset を upload することになります。
しかし、 Immutable Release ではあとから asset を upload できません。
ではどうやって asset を upload すればいいのかというと、まず draft で release を作ってから upload し、その後 draft を解除する必要があります。

GitHub CLI の gh release create で asset を upload する際も実は内部的に一回 draft で release を作成しています。

https://github.com/cli/cli/blob/e40170b263834238489dbcb4fa3a7221a19d8882/pkg/cmd/release/create/create.go#L486-L498

https://github.com/cli/cli/blob/e40170b263834238489dbcb4fa3a7221a19d8882/pkg/cmd/release/create/create.go#L500

https://github.com/cli/cli/blob/e40170b263834238489dbcb4fa3a7221a19d8882/pkg/cmd/release/create/create.go#L537

https://github.com/cli/cli/blob/e40170b263834238489dbcb4fa3a7221a19d8882/pkg/cmd/release/create/create.go#L543-L544

Immutable Release を有効化する前に気をつけること

CI で Release を作成してから asset を upload している場合、 upload に失敗するようになるので注意が必要です。
一回 draft で release を作成してから upload する必要があります。
(先述の通り、 gh release create も内部的には draft で release を作成してから upload しています)

GitHub Actions の v1 みたいな tag は引き続き更新できる

GitHub Actions のバージョニングでは v1, v2 みたいな major version だけの tag がよく作られます。
GitHub が提唱しています。

https://docs.github.com/ja/actions/how-tos/create-and-publish-actions/release-and-maintain-actions#example-developer-process

セマンティックにバージョン管理されたタグ (たとえば、v1.1.3) を使用してリリースを作成し、最新の適切なコミットに合わせてメジャー (v1) およびマイナー (v1.1) タグを最新の状態に保つことをお勧めします。

余談ですが、自分はこの tag が好きではないので自分が開発する action では一切作りません。
バージョンは固定すべきだと考えているからです。

これらの tag は新しいバージョンが出るたびに作り直すことになりますが、 Immutable Releases を有効にするとそれができなくなるのではないかと思う方もいるかもしれません。
しかし、結論を言うと問題なく tag を作り直すことができます。
なぜなら、先述の通り tag に紐づく Release を作らない限り、 tag は mutable のままだからです。
GitHub Actions の semver vX.Y.Z に対し GitHub Release を作る場合でも、通常 v1 のような tag に対して Release は作らないはずなので、 Immutable Release を有効にしても問題なく v1 のようなタグを更新することができます。

ただし、 v1 みたいな tag が Immutable Release と同じ SHA を指す保証はなく、改竄されるリスクはあります。
そのため、利用者側としては v1 みたいな tag は参照しないほうが無難ではないかと思います。

Immutable Release を有効化しましょう

以上、 Immutable Releases の紹介でした。
GitHub でソフトウェアをバージョニングして公開している方は是非全リポジトリで有効にしましょう。

https://github.blog/changelog/2025-08-26-releases-now-support-immutability-in-public-preview/

https://github.com/orgs/community/discussions/171210

Discussion