 id:cohalzです。この記事は、はてなのSREが毎月交代で書いているSRE連載の2025年10月号の記事です。9月の記事は
id:cohalzです。この記事は、はてなのSREが毎月交代で書いているSRE連載の2025年10月号の記事です。9月の記事は id:s-shiroのCloudFront標準ログ(v2)をカスタマイズして便利に使う工夫でした。
id:s-shiroのCloudFront標準ログ(v2)をカスタマイズして便利に使う工夫でした。
みなさん組織でGitHubを安全に使えていますか?
こうした問いに答えるため、安全に利用するためのポリシーをはてな社内でいくつか設定していきました。今回はそのうち、最近利用できるようになった機能を中心に以下の2つについて話していきます。
- Enforce SHA pinningの有効化
- Owner権限を持つ人を減らす
また最後にリポジトリ・プロジェクトの管理者を調べるための方法についても付録として紹介していきます。
Enforce SHA pinningの有効化への道のり
最近大きく話題になっているセキュリティリスクといえばサプライチェーン攻撃で、2025/3にはGitHub Actionsを使ったサプライチェーン攻撃が話題になりました。
対策として、以前にこのDeveloper BlogでGitHub Actionsのバージョン指定をコミットハッシュで固定(SHA pinning)する方法を紹介しました。
こういったハッシュ固定を社内では推奨としてきましたが、強制力はなくどこでサプライチェーン攻撃の影響を受けるか把握が難しい状態でした。
そんな中、2025/8 にGitHubの新機能としてハッシュ固定されてないワークフローを実行できないような設定ができるようになりました。
この設定はリポジトリごとの他に組織全体で強制的に有効することができます。
はてなではこの設定を組織全体で有効にする方針とし、ハッシュ固定の指定にする変更を進めることにしました。
しかし単純に固定にするだけではEnforce SHA pinningの条件を満たせずエラーになるケースがあったのでそちらの紹介をしていきます。
Enforce SHA pinningができる条件
どういうケースでエラーになるかというと、使用しているワークフローがComposite Actionになっており、他のワークフローに依存している場合、その依存ワークフローのバージョン指定が固定されていなかった場合も実行できなくなることです。
そういったワークフローがあった場合には、組織内のリポジトリだけでなくそのComposite Actionのリポジトリに対しても対応を進めていく必要があります。ピン留めするようにパッチを送ったり、メンテされていないものはforkするなどが必要です。
actions/upload-pages-artifact のような公式のactionでもそういった依存があるケースがあるのを確認できています。
そしてそういったケースの検出にpinactやRenovateのpinDigestsだけではそういったものは検出できないのに注意が必要です。
そのため、組織で一括で有効にしたいという場合にはいきなり有効にするのではなく、組織内の各リポジトリで安全に移行できるよう調査・対応期間を設けることが良いと思います。
社内では各リポジトリについて、依存を含めピン留めされているかを以下の手順で確認するツールを作成することで安全に対応を進めるようにしました。
確認手順
- リポジトリのワークフローファイルを確認し利用しているアクションの一覧を出す
- そのアクションのリポジトリをそのバージョンで開き /action\.ya?ml/ファイルが存在するか確認する
- /action\.ya?ml/ファイルが存在する場合はそこで利用しているアクションの一覧を出しそれに対して2を再帰的に実行する
- これを全リポジトリに対し実行する
前述の通り、強制の設定はリポジトリごとに個別に有効にすることもできるので、全体で強制する前に対応ができているかを実際に確認し先に有効にするということも可能です。
つまりピン留め機能を強制するにあたっての注意事項は下のようになります。
- 単に今のバージョンでピン留めするだけでは不十分なケースがある
- 場合によってはワークフローの最新化が必要
- 最新化をしても元のワークフローが対応していないことがある
 
- 設定を有効化した際にすぐ状態を確認できるわけではなく、実行時にエラーになるため事前の確認が難しい
- ちなみに失敗する場合はワークフローの最初に実行されるSet up jobで失敗するため、中途半端にジョブが実行されることはない
 
Owner権限を持つ人を減らすための道のり
はてなでは多くのエンジニアがOwner権限を持つ状態になっていました。
これは以前にセルフホスト版のGitHub Enterpriseを多く利用していた頃の名残で、github.comに各チームが移行する際に不便がないよう権限設計もそのままとし、最近までその設計で運用していたという事情もありました。
2FAやSAML認証の強制化によりアカウント乗っ取りのリスクは軽減しているものの、間違って強い権限で操作をしてしまうなどのリスクは引き続きある状態でした。
はてなで様々なプロダクトを開発していく中で、リポジトリに強い権限を持つ人を制限したいという需要も高まり、Owner権限を持つ人を減らしていくことになりました。
単にOwner権限をいきなり剥奪するとなると、今までできたことができなくなるため人によっては仕事に支障が出たり、権限を持つ人に依頼する作業と待ちが発生するなど開発効率の低下を招く可能性もあるため、丁寧に変更していく必要があります。
そのため、はてなでは変更する前に告知を行い、事前に対応する内容や余裕を持った変更スケジュールを提示することで安全に移行することにしました。
普段から操作をするリポジトリやプロジェクトの権限に関してはチームに権限をつけることで対応できますが、
それだけでは困るケースがいくつかありそれらの対処について紹介します。
Organizationレベルのロールを利用する
チームによっては管理するリポジトリが数十とあるケースも多く存在します。
そういった数を管理する上でリポジトリごとに設定していくよりも、多くのリポジトリで一括で使えるようOrganizationの設定の一部を許可したいことがあります。
例えばGitHub Appsの管理やOrganizationレベルでのシークレットの管理がそれに当たります。
GitHubにはOrganizationレベルのロールを設定でき、必要な権限を個人やチームに設定することができます。
以前から事前定義のロールは存在しましたが、2023/11から必要な権限だけを設定できるカスタムロールが利用可能になりました。
前述したGitHub Appsの作成やシークレットの管理もOrganizationのロールで権限を個別に設定できるため、必要な人に必要なだけの権限を設定しやすくなりました。
また、直近である2025/10/23にリリースされたTerraform Provider GitHub v6.7.0から組織のロールをTerraform管理できるようになり、誰がどのような権限を持つかを変更管理できるようになりました。
ちなみにTerraformで設定するための権限一覧はドキュメントからは見つかりませんがhttps://github.com/organizations/[org]/settings/org_roles/new を開きDevToolsなどから下記のURLのレスポンスを確認することで一覧を確認することができます。
- https://github.com/organizations/[org]/settings/org_roles/new/fgp_metadata(Organizationの権限)
- https://github.com/orgs/[org]/custom_roles/repository_permissions(リポジトリの権限)
チーム外のリポジトリにプルリクエストを出すには
Ownerでない人はwrite権限を持たないリポジトリに対してのpushを行えません。
はてなではチーム外のリポジトリであっても社内の通りすがりの人がCI/CDの周りの設定やバージョンアップなどを行うこともあり、そういったケースを考慮する必要がありました。
権限のないリポジトリにPRを送るにはOSSのようなパブリックリポジトリと同様にforkをする運用に変更する形になっていきます。
しかし、以下の理由からはてなでは以前よりリポジトリ単位でforkを禁止する設定が広く有効になっていました。
- 間違って個人のリポジトリにforkしてしまう事故の危険性があった
- forkしたリポジトリからプルリクエストを作成した際、ワークフローが元リポジトリのシークレットを参照できなかった
- そもそも2022/6以前は組織内に同じ可視性でforkすることができなかった
このため以前はリポジトリのwrite権限を広くつけることによって対応していました。
これらの設定は今は設定によって解決できるようになっています。
まず、同じ組織に可視性でforkする機能と組織外の個人にforkをできないようにする設定は2022/6から利用可能になりました。
また、組織内でforkしたリポジトリからのプルリクエストからでもワークフローでシークレットを読めるようにできる設定が2020/8から利用可能になりました。
これらの設定はリポジトリごとに変更することができ、以前と同様に参照をできないようにしたり、実行に承認を必要とする設定も遅れて2022/11に可能になりました。
これらの新機能によってチーム外のリポジトリに対してもリポジトリに広くwrite権限をつけることなく、安全にforkを用いたプルリクエストを作成するというフローを行えるようになり、Owner権限でなくとも暮らしやすくなりました。
おわり
Enforce SHA pinningと脱Owner権限について紹介しました。SHA pinningはかなり大変ではありますが設定を有効にできるとサプライチェーン攻撃へのリスクをかなり軽減できます。
GitHub Appsの組織へのインストールなどOwnerにしかできない権限はまだ存在しますが、以前に比べてもだいぶ少なくなってきたと感じます。
以前にもOwner権限の見直しを検討していたことはありましたが、最近のアップデートにより不便でない形でようやく実現できるようになりました。
Changelogを見ると色々アップデートされているので、GitHubの運用管理について定期的に見直ししてみるのはいかがでしょうか。
付録: リポジトリ・プロジェクトの管理者を調べる方法
こういったGitHubのポリシーを変更するにあたって各リポジトリ・プロジェクトの管理者を調べることが何度かあったため、付録として調べ方を書いておきます。
トピックで調べる
GitHubリポジトリのトピックは検索クエリとして利用することができます。
topic:perl のように検索でき、トピックのついている数でも topics: のように検索することができます。
これを元に適切なトピックをリポジトリにつけることで分類がしやすい状態にすることができます。
リポジトリのコラボレーターを調べる
リポジトリの「Collaborators and teams」はAPIで取得することもできます。
各リポジトリごとにadmin権限で設定されているチームの一覧をを下のようなコマンドで調べていくことができます。
gh api -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" /repos/[org]/[repo]/teams --jq '.[] | select(.permission == "admin") | .name'
なお、GraphQL APIでは同様の情報を取得する方法は現時点ではないようです。
プロジェクトのコラボレーターを調べる
プロジェクトはGraphQL APIを用いてチームを確認することができます。
gh api graphql --paginate -f query=' query($endCursor: String) { organization(login:"[org]") { projectsV2(first: 100, after: $endCursor) { nodes { title teams(first: 5) { nodes { name } } } pageInfo { hasNextPage endCursor } } } } '
ただし、各チームがどんな権限でプロジェクトに紐づいているかを確認する方法はないようです。
github.com
また、プロジェクトはリポジトリと異なりトピックを設定することはできません。
以上付録のコーナーでした。
 
  