GitHub Actions の支払いを管理する GitHubは、macOSランナーのホストにMacStadiumを使用しています。
概要
このガイドでは、特定の GitHub Actions 機能のセキュリティ強化を設定する方法について説明します。 GitHub Actions の概念について理解を深めるには、「GitHub Actions の中核的概念」を参照してください。
シークレットを使用する
機密性の高い値は、平文としてワークフローファイルに保存するのではなく、シークレットとして保存してください。 シークレットは Organization またはリポジトリレベルで設定でき、機密情報を GitHub Enterprise に保存できます。
シークレットは Libsodium sealed boxes を使用するため、GitHub Enterprise に到達する前に暗号化されます。 これは、UI を使用して、または REST API を介してシークレットが送信されたときに発生します。 このクライアント側の暗号化により、GitHub Enterprise のインフラストラクチャ内での偶発的なログ(例外ログやリクエストログなど)に関連するリスクを最小限に抑えることができます。 シークレットがアップロードされると、GitHub Enterprise はそれを復号化して、ワークフローランタイムに挿入できるようになります。
偶発的な開示を防ぐために、GitHub Enterprise は、実行ログに表示されるシークレットを編集しようとするメカニズムを使用しています。 この編集は、設定されたシークレットの完全一致、および Base64 などの値の一般的なエンコーディングを検索します。 ただし、シークレットの値を変換する方法は複数あるため、この編集は保証されません。 そのため、シークレットを確実に編集し、シークレットに関連する他のリスクを制限するために実行する必要がある、特定の予防的ステップと推奨事項は次のとおりです。
- 構造化データをシークレットとして使用しない
- 非構造化データは、ログ内のシークレットの編集失敗の原因となる可能性があります。これは、編集が特定のシークレット値の完全一致を見つけることに大きく依存しているためです。 たとえば、JSON、XML、または YAML(または同様)の Blob を使用してシークレット値をカプセル化しないでください。シークレットが適切に編集される可能性が大幅に低下するためです。 代わりに、機密値ごとに個別のシークレットを作成します。
- ワークフロー内で使用されるすべてのシークレットを登録する
- シークレットを使用してワークフロー内で別の機密値を生成する場合は、生成された値を正式にシークレットとして登録して、ログに表示されたときに編集されるようにする必要があります。 たとえば、秘密鍵を使用して署名済み JWT を生成し、Web API にアクセスする場合は、その JWT をシークレットとして登録してください。そうしない場合、ログ出力に入力されても編集されません。
- シークレットの登録は、あらゆる種類の変換/エンコーディングにも適用されます。 シークレットが何らかの方法で変換された場合(Base64 や URL エンコードなど)、新しい値もシークレットとして登録してください。
- シークレットの処理方法を監査する
- シークレットの使用方法を監査し、シークレットが想定どおりに処理されていることを確認します。 これを行うには、ワークフローを実行しているリポジトリのソースコードを確認し、ワークフローで使用されているアクションを確認します。 たとえば、意図しないホストに送信されていないか、またはログ出力に明示的に出力されていないかを確認します。
- 有効/無効な入力をテストした後、ワークフローの実行ログを表示し、シークレットが正しく編集されているか、表示されていないかを確認します。 呼び出しているコマンドまたはツールがどのようにしてエラーを
STDOUTおよびSTDERRに送信するかは必ずしも明らかではなく、シークレットはその後エラーログに記録される可能性があります。 そのため、有効な入力と無効な入力をテストした後、ワークフローログを手動で確認することをお勧めします。
- スコープが最小限の資格情報を使用する
- ワークフロー内で使用されている認証情報に必要な最小限の権限があることを確認し、リポジトリへの書き込みアクセスを持つすべてのユーザが、リポジトリで設定されたすべてのシークレットへの読み取りアクセスを持っていることに注意してください。
- 登録されたシークレットの監査とローテーション
- 登録されたシークレットを定期的に確認して、現在も必要であることを確認します。 不要になったものは削除してください。
- シークレットを定期的にローテーションして、不正使用されたシークレットが有効である期間を短縮します。
サードパーティアクションを使用する
ワークフロー内の個々のジョブは、他のジョブと相互作用(および侵害)する場合があります。 たとえば、後のジョブで使用される環境変数をクエリするジョブ、後のジョブが処理する共有ディレクトリにファイルを書き込むジョブ、または Docker ソケットとやり取りして他の実行中のコンテナを検査してコマンドを実行することにより、さらに多くのディレクトリを作成するジョブなどです。
これは、ワークフロー内の 1 つのアクションへの侵害が非常に重要になる可能性があるということです。その侵害されたアクションがリポジトリに設定されたすべてのシークレットにアクセスし、GITHUB_TOKEN を使用してリポジトリに書き込むことができるためです。 したがって、GitHub のサードパーティリポジトリからアクションを調達することには大きなリスクがあります。 次のような適切な方法に従うことで、このリスクを軽減することができます。
-
アクションを完全なコミット SHA にピン止めする
現在、アクションを不変のリリースとして使用する唯一の方法は、アクションを完全なコミット SHA にピン止めすることです。 特定の SHA にピン止めすると、有効な Git オブジェクトペイロードに対して SHA-1 衝突を生成する必要があるため、悪意のある人がアクションのリポジトリにバックドアを追加するリスクを軽減できます。
警告: コミット SHA の短いバージョンは安全ではないため、アクションの Git リファレンスの指定には使用しないでください。 リポジトリネットワークの仕組みにより、どのユーザもリポジトリをフォークし、短い SHA と衝突するよう細工されたコミットをプッシュできます。 これにより、その SHA の後続のクローンがあいまいなコミットになるため失敗します。 その結果、短縮された SHA を使用するワークフローはすぐに失敗します。
-
アクションのソースコードを監査する
アクションが想定どおりにリポジトリとシークレットのコンテンツを処理していることを確認します。 たとえば、シークレットが意図しないホストに送信されていないか、または誤ってログに記録されていないかを確認します。
-
作成者を信頼できる場合に限り、アクションをタグにピン止めする
コミット SHA に対するピン止めが最も安全なオプションですが、タグを指定する方が便利で広く使用されています。 タグを指定する場合は、アクションの作成者が信頼できることを確認してください。 GitHub Marketplace の「Verified creator」バッジは便利な判断材料で、 GitHub で身元が確認されたチームによって作成されたアクションであることを示しています。 作者が信頼できる場合でも、このアプローチにはリスクがあることに注意してください。悪意のある人がアクションを保存しているリポジトリにアクセスすると、タグが移動または削除される可能性があります。
リポジトリ間のアクセスを検討する
GitHub Enterprise は、意図的に一度に単一のリポジトリに対してスコープされます。 ワークフロー環境で使用される GITHUB_TOKEN は、書き込みアクセスユーザと同じレベルのアクセスを許可します。書き込みアクセスを持つユーザは、ワークフローファイルを作成または変更することによってこのトークンにアクセスできるためです。 ユーザはリポジトリごとに特定の権限を持っているため、1 つのリポジトリの GITHUB_TOKEN に別のリポジトリへのアクセスを許可すると、慎重に実装しない場合 GitHub 権限モデルに影響します。 同様に、GitHub 認証トークンをワークフロー環境に追加する場合は注意が必要です。これは、コラボレータに誤って広範なアクセスを付与することにより、GitHub アクセス許可モデルにも影響を与える可能性があるためです。
GitHub ロードマップでは、GitHub Enterprise 内のリポジトリ間アクセスを可能にするフローをサポートする計画がありますが、この機能はまだサポートされていません。 現在、権限のあるリポジトリ間のやり取りを実行する唯一の方法は、ワークフロー環境内に GitHub 認証トークンまたは SSH キーをシークレットとして配置することです。 多くの認証トークンタイプでは特定のリソースへの詳細なアクセスが許可されていないことから、意図したものよりはるかに広範なアクセスを許可できるため、間違ったトークンタイプを使用すると重大なリスクが生じます。
次のリストでは、ワークフロー内のリポジトリデータにアクセスするための推奨アプローチを優先度の高い順に説明しています。
- ワークフロー環境の
GITHUB_TOKEN- このトークンは、ワークフローを呼び出した単一のリポジトリに意図的にスコープが設定されており、リポジトリの書き込みアクセスユーザと同じレベルのアクセス権を持っています。 トークンは各ジョブが開始する前に作成され、ジョブが終了すると期限切れになります。 詳しい情報については「GITHUB_TOKENでの認証」を参照してください。
- 可能な場合は、常に
GITHUB_TOKENを使用する必要があります。
- リポジトリのデプロイキー
- デプロイキーは、単一のリポジトリへの読み取りまたは書き込みアクセスを許可する唯一の認証情報タイプの 1 つであり、ワークフロー内の別のリポジトリとのやり取りに使用できます。 詳しい情報については、「デプロイキーを管理する」を参照してください。
- デプロイキーは Git を使用してリポジトリに複製およびプッシュできるだけであり、REST または GraphQL API とのやり取りには使用できないため、要件に適さない場合があることに注意してください。
- GitHub App トークン
- GitHub Apps は、選択したリポジトリにインストールでき、リポジトリ内のリソースに対する詳細な権限を持つこともできます。 Organization の内部で GitHub App を作成し、ワークフロー内でアクセスする必要があるリポジトリにインストールして、それらのリポジトリにアクセスするためのワークフロー内のインストールとして認証できます。
- 個人アクセストークン
- 自分のアカウントから個人アクセストークンを使用しないでください。 これらのトークンは、アクセスできる Organization 内のすべてのリポジトリ、およびユーザアカウントのすべての個人リポジトリへのアクセスを許可します。 これにより、ワークフローが含まれているリポジトリのすべての書き込みアクセスユーザに間接的に広範なアクセス権が付与されます。 さらに、後で Organization を離れると、このトークンを使用するワークフローはすぐに中断され、この問題のデバッグが困難になる場合があります。
- 個人アクセストークンを使用する場合は、ワークフローに必要な特定のリポジトリへのアクセスのみが許可される新しいアカウント用に生成されたものを使用してください。 このアプローチはスケーラブルではないため、デプロイキーなどの代替案を優先して避ける必要があります。
- ユーザアカウントの SSH キー
- ワークフローでは、ユーザアカウントの SSH キーを使用しないでください。 これらは、個人アクセストークンと同様に、すべての個人リポジトリと、Organization のメンバーシップを通じてアクセスできるすべてのリポジトリに読み取り/書き込み権限を付与します。 これにより、ワークフローが含まれているリポジトリのすべての書き込みアクセスユーザに間接的に広範なアクセス権が付与されます。 リポジトリのクローンまたはプッシュのみを実行する必要があり、パブリック API とやり取りする必要がないため、SSH キーを使用する場合は、代わりに個別のデプロイキーを使用する必要があります。
セルフホストランナーを強化する
GitHub でホストされたランナーは、一過性でクリーンな隔離された仮想マシン内でコードを実行します。つまり、この環境を永続的に危険にさらしたり、ブートストラッププロセス中にこの環境に置かれた以上の情報にアクセスしたりする方法はありません。
GitHub Enterprise のセルフホストランナーは、一過性でクリーンな仮想マシンでの実行に関する保証がなく、ワークフロー内の信頼されていないコードによって永続的に侵害される可能性があります。
そのため、GitHub Enterprise のパブリックリポジトリにセルフホストランナーを使用することはほとんどありません。これは、ユーザがリポジトリに対してプルリクエストを開き、環境を危険にさらす可能性があるためです。 同様に、プライベートリポジトリでセルフホストランナーを使用する場合は注意してください。リポジトリをフォークして PR を開くことができるユーザ(一般にリポジトリへの読み取りアクセス権を持つユーザ)は、シークレットへのアクセスと、リポジトリへの書き込みアクセス許可を付与する、より特権的な GITHUB_TOKEN を取得して、セルフホストのランナー環境を危険にさらすことができるためです。
次のように、セルフホストランナーマシンの環境も考慮する必要があります。
- セルフホストランナーとして設定されたマシンにはどのような機密情報が存在するか。 たとえば、SSH 秘密鍵、API アクセストークンなどです。
- マシンが機密性の高いサービスにネットワークアクセス可能か。 たとえば、Azure または AWS メタデータサービスなどです。 この環境での機密情報量は最小限に抑える必要があります。ワークフローを呼び出すことができるすべてのユーザがこの環境にアクセスできることを常に意識しておいてください。