はじめに
依存関係の更新やビルドツールの実行は、開発の現場で日常的に行われる作業です。しかし、インストールやビルドの途中で悪意のあるコードが実行されると、その開発端末や CI/CD ランナーから利用できるクラウドの認証情報を通じて、影響がクラウド環境まで広がる場合があります。
Qualys は 2026 年 9 月 28 日に公開したブログ記事「The Developer is the New Perimeter」で、パッケージのインストール時に実行されるコードが開発者や CI の認証情報へ到達し、クラウドの侵害につながる流れを整理しています。
一方で、実務の担当者が判断に迷うのは「自社の開発端末や CI/CD にどの認証情報があり、侵害が疑われたらどのクラウド環境まで調べるべきか」という点です。本記事では、個別事件の詳細ではなく、実行環境、利用可能な認証情報、操作できるクラウド資源、確認・対応の対応関係を、AWS と GitHub Actions を中心に整理します。
- 開発端末や CI/CD ランナーにある認証情報と、到達できるクラウド資源の対応
- 依存関係への包含、インストール、コード実行、窃取、不正アクセスを分けて判断する考え方
- 依存関係の取得・ビルドとデプロイを分離する際の確認観点
- OIDC、IMDSv2、MFA、SHA ピン留めなどの対策が効く範囲と限界
- 侵害が疑われた場合の封じ込め、認証情報の無効化、CloudTrail で調査できる範囲
結論として、悪意のあるパッケージを削除し、元のキーを更新しただけでは対応は完了しません。悪意のあるコードが実行された環境から利用できた認証情報と権限を洗い出し、その権限で操作できたクラウド資源を調査対象にすることが初動の軸になります。予防では、コードが実行される機会を減らす、実行環境から使える権限を絞る、クラウド側で不正な操作を検知して止める、の三つを組み合わせます。
サプライチェーン攻撃がクラウド侵害につながる仕組み
攻撃者が狙うのは、本番のアプリケーションそのものではなく、開発端末や CI/CD ランナーでのコードの実行機会と、その環境に置かれた認証情報です。ここでは、攻撃経路と影響判断の区切り方を整理します。
アプリケーションの起動前にコードが実行される場合がある
npm では、パッケージの package.json に定義された preinstall、install、postinstall などのライフサイクルスクリプトが、インストールの過程で実行され得ます。ただし、実際に実行されるかは npm のバージョンと設定によって異なります。たとえば npm 12 の公式資料では、依存パッケージのインストールスクリプトは既定でブロックされ、package.json の allowScripts で許可されたパッケージだけが実行されると説明されています(npm Docs)。影響を判断する際は、実行時の npm のバージョンと許可設定を確認します。
挙動はパッケージ管理ツールごとにも異なります。Bun は既定では任意のライフサイクルスクリプトを実行しませんが、許可リストに含まれるパッケージのスクリプトは実行します。trustedDependencies を定義していない場合は Bun が用意した既定の許可リスト、定義した場合はそこに列挙したパッケージが対象です(Bun Docs)。Python、Ruby、Go などのエコシステムでも、コードが実行される契機と制御方法はツールや配布形式によって異なるため、利用しているツールの公式資料で確認する必要があります。
また、入口は依存関係だけではありません。CI/CD で使うスキャナーやアクションなどの開発ツール自体が侵害された場合も、そのツールはジョブの環境変数やファイルにアクセスできる状態で実行されます。postinstall を悪用した具体的な手口と検出方法は、『axios npm 1.14.1 / 0.30.4 のマルウェア混入と検出・修復の手順』で解説しています。
「実行された」と「侵害された」を分けて判断する
影響判断では、次の段階を区別します。どの段階まで確認できたかによって、説明できる事実と必要な対応の範囲が変わります。
- 依存関係への包含
-
対象バージョンが、ロックファイルやマニフェストで依存関係として解決されていた状態です。ロックファイルは依存関係の解決結果を示すものであり、それだけでは対象の端末やランナーへのインストールや、コードの実行は証明できません。
- インストール
-
対象の端末やランナーで、該当バージョンが実際に取得・展開された状態です。インストールやジョブのログ、パッケージのキャッシュ、node_modules などの配置状況で確認します。
- 悪意あるコードの実行
-
悪意のあるスクリプトやペイロードが実行された、または実行を否定できない状態です。実行時のツールのバージョンと設定、スクリプトが実行される条件、ジョブログ、プロセスや通信の記録を突き合わせて判断します。実行の痕跡が見つからないことだけでは、実行されなかったとは判断できません。
- 認証情報へのアクセス可能性
-
実行時点で、そのプロセスが読み取れた環境変数や設定ファイル、ジョブに渡された Secrets、取得可能なトークンの範囲です。窃取の証拠がなくても、アクセスできた認証情報は漏えいした可能性があるものとして扱います。
- 認証情報の窃取
-
外部への送信や、攻撃者が管理する場所への保存が確認された状態です。通信ログやマルウェアの解析結果から判断しますが、痕跡が残らない場合もあります。
- クラウドへの不正アクセス
-
窃取された認証情報による API 呼び出しが、クラウドの監査ログで確認された状態です。確認できるのは、該当するログを収集・保存していた範囲に限られます。
窃取や不正利用の証拠が揃うのを待つと、その間も認証情報は有効なまま残ります。Qualys も、未検証のパッケージを実行した CI ランナーを侵害された可能性があるものとして扱い、そのランナーがアクセスできたシークレットを更新するよう推奨しています。本記事でも、悪意あるコードの実行を確認した時点、または実行を否定できない時点で、認証情報の無効化とクラウド側の調査を始めることをおすすめします。
事例: CI/CD から取得された API キーによる AWS アカウントの侵害
原典で経緯を確認できる例として、CERT-EU が 2026 年 4 月 2 日に公開した欧州委員会のクラウド侵害の報告があります。CERT-EU は、Trivy のサプライチェーン侵害を通じて 2026 年 3 月 19 日に AWS の API キーが攻撃者に取得されたと、高い確度で評価しています。
参考: CERT-EU
“This key granted control over other AWS accounts affiliated with the European Commission.”
(このキーは、欧州委員会に関連する他の AWS アカウントに対する管理権限を持っていました。)
https://cert.europa.eu/blog/european-commission-cloud-breach-trivy-supply-chain
報告によると、攻撃者は取得した認証情報で既存のユーザーに新しいアクセスキーを作成して付与し、偵察を行ったうえでデータを持ち出しました。欧州委員会は 3 月 24 日に API の不正利用などのアラートを受けて対応を開始し、侵害されたアカウントの権限を取り消し、関係するアクセスキーを無効化・削除しています。
この事例が示しているのは、被害の大きさがパッケージそのものではなく、実行環境から取得できた認証情報の権限で決まるという点です。Trivy 侵害自体の経緯や GitHub Actions の SHA ピン留めの設定は、『Trivy 侵害から始まったサプライチェーン攻撃|CI/CD の防御策と SHA ピン留め』で扱っています。
npm エコシステムでも、2025 年 9 月に自己増殖型のワーム「Shai-Hulud」が確認されました。CISA の注意喚起によると、このマルウェアは環境内の認証情報を探索し、GitHub の PAT や、AWS・Google Cloud・Azure の API キーを標的にしていました。なお、Qualys の記事は 2026 年 9 月 28 日の公開ですが、記事中で紹介されている攻撃は 2025 年 9 月から 2026 年 5 月にかけて観測されたものです。

開発環境とクラウド認証情報の棚卸し
侵害時に「どこまで調べるか」を短時間で判断するには、平時から実行環境ごとの認証情報と権限の対応を把握しておく必要があります。ここでは、代表的な認証情報を「何を持っているか」から「何を操作できるか」へたどれる形で整理します。
認証情報の棚卸し表
| 認証情報 | 実行環境からのアクセス経路 | 到達先・権限 | 調査・対応の確認点 |
|---|---|---|---|
| AWS IAM ユーザーのアクセスキー | 開発端末の ~/.aws/credentials、CI の環境変数や Secrets | IAM ユーザーに付与されたポリシーの範囲。引き受け可能なロールがあれば、その先の権限も含む | アクセスキー ID、最終使用日時、付与されたポリシー、引き受け可能なロール |
| AWS の一時認証情報(ロールのセッション) | CLI のキャッシュ、インスタンスメタデータ、OIDC で取得したセッション | ロールの権限の範囲。有効期限まで利用できる | ロール ARN、セッションの発行日時、ロールの信頼ポリシー(誰が再取得できるか) |
| GitHub Actions の OIDC で引き受ける AWS ロール | id-token: write を持つジョブで取得したトークンを交換 | 信頼ポリシーの条件を満たすジョブに対して、ロールの権限 | 信頼ポリシーの条件(リポジトリ、ブランチ、environment)、そのジョブで実行された依存関係やツール |
| Azure のサービスプリンシパル資格情報、マネージド ID | シークレットや証明書は CI の Secrets や設定ファイル。マネージド ID は割り当て先のリソース上で動作するコードがトークンを要求 | Azure RBAC で割り当てられたロールの範囲 | アプリケーション(クライアント)ID、ロールの割り当て範囲、登録済みの資格情報、サインインログ |
| Google Cloud のサービスアカウントキー | 開発端末や CI に置かれたキーファイル | キーからアクセストークンを取得し、サービスアカウントの権限で API を呼び出せる | キー ID、サービスアカウントに付与されたロール、権限借用が可能な関係、監査ログ |
| GitHub の PAT | 開発端末の Git 認証情報、CI の Secrets | トークンのスコープと、所有者がアクセスできるリポジトリ・組織の範囲 | トークンの所有者、スコープと対象リポジトリ、有効期限、組織の監査ログ |
| GitHub Actions の Secrets、GITHUB_TOKEN | ジョブに渡された値と、ジョブ内で参照できる github.token | Secrets の利用先の権限。GITHUB_TOKEN は permissions で設定した範囲のリポジトリ操作 | どのジョブ・イベントで Secrets が渡るか、permissions の既定値、environment の保護ルール |
| Kubernetes の kubeconfig | 開発端末の ~/.kube/config、CI の Secrets | 参照先のクラスターと、認証されたユーザーやサービスアカウントの RBAC 権限 | 参照先クラスターとコンテキスト、認証方式(トークン、証明書、クラウドの認証コマンドなど)、RBAC のバインディング |
同じクラウドの認証情報でも、長期のキーをファイルで持つ方式と、実行環境がその場でトークンを取得する方式では、確認すべき点が異なります。Azure のマネージド ID は、割り当てたリソース上のアプリケーションが資格情報を管理せずにトークンを取得できる仕組みです(Microsoft Learn)。Google Cloud は、ユーザー管理のサービスアカウントキーをできるだけ避け、他の認証方式を使うよう推奨しています(Google Cloud Docs)
保存された秘密情報がない方式でも、侵害された実行環境からは同じ権限を使える可能性があるため、影響確認の対象から外すことはできません。
棚卸しの進め方
開発端末、GitHub ホスト型ランナー、セルフホスト型ランナー、ビルドサーバー、コンテナのビルド環境など、依存関係の取得やビルドを行う場所を洗い出します。GitHub は、セルフホスト型ランナーはワークフロー内の信頼されないコードによって永続的に侵害され得るとしているため、ホスト型ランナーとは分けて管理します(GitHub Docs)。
設定ファイル、環境変数、ジョブに渡される Secrets、OIDC で取得できるロール、インスタンスメタデータなど、その環境で動作するコードが取得できるものを対象にします。記録するのは値ではなく、キー ID、ロール ARN、クライアント ID などの識別子です。
ポリシー、ロールの割り当て、引き受け可能なロール、Kubernetes の RBAC を確認し、到達できるアカウント、サブスクリプション、プロジェクトを一覧にします。AWS は、長期のアクセスキーについて最終使用情報を使って不要なキーを特定・削除するよう推奨しています(AWS IAM ベストプラクティス)。アクセスキーの最終使用日時、サービス、リージョンは次のコマンドで確認できます(AWS CLI リファレンス)
aws iam get-access-key-last-used --access-key-id <アクセスキー ID>クラウドの監査ログ、GitHub の監査ログ、ワークフローの実行ログが、どの範囲をどれだけの期間保存しているかを確認します。侵害時に調べられる範囲は、この時点の設定で決まります。
棚卸しや調査では、認証情報の値を画面に表示したり、ログに出力したりしないでください。識別子と権限、利用履歴で確認することで、確認作業そのものによる露出を避けられます。
GitHub Secrets に保存することと、実行中のコードから守ることは別
GitHub Actions の Secrets は、秘密情報をリポジトリや environment に保管する仕組みですが、ジョブに渡された値は、そのジョブで動作するコードから参照できます。GitHub は、ワークフロー内のアクションが侵害された場合の影響を次のように説明しています。
参考: GitHub Docs「Secure use reference」
“a compromise of a single action within a workflow can be very significant”
(ワークフロー内の単一のアクションが侵害されると、非常に重大な影響を及ぼし得ます。)
https://docs.github.com/en/actions/reference/security/secure-use
同じ資料では、侵害されたアクションがリポジトリに設定されたシークレットにアクセスし、GITHUB_TOKEN でリポジトリへ書き込める可能性があるとしています。また、ログ上のシークレットの自動マスキングは保証されないとも明記しています。ログでマスクされていることは、実行中のコードに値を読まれていないことを意味しません。
確認すべきは保存場所ではなく、どのジョブに、どの条件で値が渡るかです。environment にレビュー担当者の承認(required reviewers)を設定すると、承認されるまでジョブは environment のシークレットにアクセスできません。GITHUB_TOKEN は既定の権限をリポジトリのコンテンツの読み取りに限定し、必要なジョブだけで引き上げることが推奨されています。
攻撃経路を狭める対策とその限界
単一の対策で攻撃経路全体を防ぐことはできません。Qualys も三つの制御点で攻撃経路を分断する考え方を示しています。本記事では対策を「実行の機会を減らす」「使える権限を絞る」「クラウド側で検知して止める」の三段階に分け、それぞれの限界とあわせて整理します。
| 対策 | 主に効く段階 | 限界・確認点 |
|---|---|---|
インストール時のスクリプトの制御(ignore-scripts、allowScripts など) | 実行の機会を減らす | スクリプトを必要とするパッケージのビルドが失敗する場合がある。明示的に実行するスクリプトや、アプリケーション・テストの実行時にコードが動く経路は残る |
| ロックファイル、バージョン固定、SHA ピン留め | 実行の機会を減らす | 意図しない更新は防げるが、固定した対象自体の安全性は保証しない |
| 脆弱性スキャン、SBOM、依存関係のレビュー | 実行の機会を減らす | 既知の脆弱性情報や公開済みの判定に依存し、公開直後の悪意あるパッケージを検出できない場合がある |
| ビルドとデプロイのジョブ分離 | 使える権限を絞る | 同じランナー、キャッシュ、成果物を共有していると分離の効果が弱まる |
| OIDC による一時認証情報 | 使える権限を絞る | 長期キーの保存は不要になるが、信頼条件を満たすジョブ内の悪意あるコードは一時認証情報を取得できる |
| IMDSv2、メタデータへのアクセス制限 | 使える権限を絞る | インスタンス上で動作するコードは IMDSv2 の手順でも認証情報を取得できる。制限は正当な SDK やエージェントに影響する |
| MFA | 使える権限を絞る | 対話的なサインインを保護するが、発行済みのアクセスキーや既存セッションによる API 呼び出しを一律には止めない |
| 監査ログの記録とアラート、組織レベルのガードレール | 検知して止める | 記録を有効にしていない種類の操作や、保存期間外の操作は調査できない |
悪意のあるコードが実行される機会を減らす
CI では、インストール時のスクリプトを止める設定が考えられます。Qualys も、運用上両立できる範囲で CI の .npmrc に ignore-scripts=true を設定するよう推奨しています。
# CI で使用する .npmrc(package.json に定義されたスクリプトを止める)
ignore-scripts=truenpm の公式資料によると、ignore-scripts を有効にしても、npm test、npm run、npm start など特定のスクリプトを明示的に実行するコマンドは、そのスクリプト自体を実行します(前後の pre / post スクリプトは実行されません)。また npm 12 では、ignore-scripts が allowScripts などによる許可より優先されるため、有効にしたままでは許可したパッケージのスクリプトも実行されません(npm Docs)。必要なパッケージだけにスクリプトの実行を認める場合は、使用している npm のバージョンで提供される許可の仕組みと、ignore-scripts との関係を確認して設定します。導入前に、ネイティブモジュールのビルドなど、スクリプトに依存する処理を洗い出してください。
ロックファイル、バージョン固定、GitHub Actions の SHA ピン留めは、参照先が気付かないうちに変わることを防ぐ対策です。一方で、固定した時点のバージョンやコミットが悪意のあるものであれば、固定によってそれを使い続けることになります。CISA も Shai-Hulud への対応として、侵害が始まる前に公開された既知の安全なバージョンへ固定するよう求めていました。固定する対象を選ぶ際は、公表されている侵害期間を避けているかを確認します。
脆弱性スキャンや SBOM は構成の把握と既知の問題の検出に役立ちますが、悪意のあるパッケージや認証情報の窃取をすべて検出できるわけではありません。たとえば GitHub は、Dependabot がアラートを作成するのはセマンティックバージョンを使うアクションに限られ、SHA にピン留めしたアクションは対象外と説明しています(GitHub Docs)。検出の仕組みごとに対象範囲を把握したうえで使います。
実行環境から使える認証情報と権限を絞る
重要な確認観点の一つが、依存関係の取得・ビルド・テストを行うジョブと、クラウドへの権限が必要なデプロイジョブの分離です。Qualys も、コードをコンパイルするだけのビルドジョブに AWS のデプロイ用認証情報を持たせるべきではないとしています。次の点を確認します。
- 依存関係の取得・ビルド・テストのジョブに、クラウドの Secrets や
id-token: writeを渡していないか - デプロイジョブはビルド済みの成果物を受け取り、新たな依存関係の取得やスクリプトの実行を最小限にしているか
- デプロイジョブに environment を設定し、対象ブランチの制限やレビュー担当者の承認を組み合わせているか
- ビルドとデプロイが、同じセルフホスト型ランナーやキャッシュを共有していないか
- 別のワークフローから受け取った成果物を、無条件に信頼できる入力として扱っていないか
GitHub Actions では、ワークフロー全体の既定権限を読み取りに絞り、OIDC トークンの要求権限をデプロイジョブにだけ付与する構成にします。次は構成の考え方を示す骨組みです。
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@<コミット SHA>
- run: npm ci
- run: npm test
# クラウドの Secrets と id-token: write は渡さない
deploy:
needs: build
runs-on: ubuntu-latest
environment: production
permissions:
contents: read
id-token: write
steps:
# ビルド済みの成果物を取得し、クラウド事業者の公式アクションで
# OIDC トークンを一時認証情報に交換してからデプロイする
- run: echo "deploy"OIDC については、GitHub が次のように説明しています。
参考: GitHub Docs「Configuring OpenID Connect in cloud providers」
“without having to store any credentials as long-lived GitHub secrets”
(長期間有効な GitHub のシークレットとして認証情報を保存する必要がありません。)
https://docs.github.com/en/actions/how-tos/secure-your-work/security-harden-deployments/oidc-in-cloud-providers
ただし、OIDC はトークンを要求したジョブを信頼条件で判定する仕組みです。信頼条件を満たすジョブの中で悪意のあるコードが実行されれば、そのコードも一時認証情報を取得・利用できます。GitHub は、信頼されないリポジトリがアクセストークンを要求できないよう、少なくとも一つの条件を定義する必要があるとしています。信頼条件をリポジトリだけでなくブランチや environment まで絞り、そのジョブで実行するコードを最小限にすることが、OIDC の効果を保つ前提になります。
短期の認証情報やマネージド ID も同様です。AWS は、EC2 上のアプリケーションがインスタンスメタデータからロールの一時認証情報を取得する手順を公開しており、IMDSv2 でもセッショントークンを取得してから要求すれば認証情報を取得できます(Amazon EC2 ユーザーガイド)。IMDSv2 は単純な GET リクエストによる取得を難しくしますが、インスタンス上で動作する悪意のあるコードから認証情報を守る手段としては限界があります。
メタデータへのアクセスを制限する場合は、その環境で正当に認証情報を取得している SDK やエージェントを先に確認します。たとえば、セルフホスト型ランナーがインスタンスのロールでデプロイしている場合、一律に遮断するとデプロイが失敗します。また、認証情報の取得経路はクラウドや実行形態(仮想マシン、コンテナ、Kubernetes の Pod など)によって異なるため、特定の IP アドレスを遮断しただけで、すべての経路を塞いだとは判断しないでください。
権限の削減や経路の制限は、ビルドやデプロイが失敗する原因になり得ます。変更前に対象の処理の利用目的と必要な権限を整理し、検証用のブランチや環境で正常に動作することを確認してから本番のパイプラインに適用することをおすすめします。
不正なクラウド操作を検知し、アクセスを止める
認証情報が持ち出された場合に備え、クラウド側の記録と制限を事前に整えておきます。AWS では、CloudTrail の証跡またはイベントデータストアで長期の記録を残し、AWS Organizations のサービスコントロールポリシー(SCP)で組織全体の権限のガードレールを設定することが推奨されています(AWS IAM ベストプラクティス)。Qualys は、侵害された認証情報による管理者ロールの作成や監査ログの無効化を、SCP などで防ぐ構成を挙げています。
監視では、アクセスキーの新規作成、ロールの信頼ポリシーの変更、新しい OIDC プロバイダーの追加、証跡の停止などを優先します。CERT-EU の事例では既存ユーザーへの新しいアクセスキーの追加が確認されており、Qualys は想定外の GitHub と AWS 間の OIDC 信頼関係の作成を監視対象に挙げています。
MFA は人の対話的なサインインを保護する有効な手段で、CISA も開発者アカウントにフィッシング耐性のある MFA を求めています。ただし、MFA を有効にしても、すでに発行されたアクセスキーや一時認証情報による API 呼び出しを一律に防げるわけではありません。窃取された認証情報への対策は、無効化、権限の最小化、監視と組み合わせて考えます。
侵害が疑われた場合の初動とクラウド側の調査
悪意のあるパッケージやツールの実行が疑われた場合、最初に確認するのは「その環境から何が使えたか」です。Qualys は、影響範囲の起点を認証情報とアクセスの範囲に置くべきだとしています。
参考: Qualys
“Package removal alone is not containment.”
(パッケージの削除だけでは、封じ込めにはなりません。)
https://blog.qualys.com/vulnerabilities-threat-research/2026/09/28/developer-new-perimeter-supply-chain-cloud-breaches
初動で並行して進める対応
次の対応は、上から順に一つずつ完了させるものではありません。認証情報の悪用が進行している可能性がある場合は、アクセスの遮断と、ログや実行履歴の保全を並行して進めます。
| 対応 | 目的 | 主な確認点 |
|---|---|---|
| 不審なジョブの停止、端末・ランナーの隔離 | 悪意のあるコードの実行継続と拡散を止める | 実行中・予約済みのワークフロー、セルフホスト型ランナーの接続、影響端末のネットワーク接続 |
| ログと実行履歴の保全 | 後から影響範囲を判断できる状態を残す | ワークフローの実行ログ、ランナーやビルドサーバーのディスクとメモリ、クラウドの監査ログのエクスポート |
| 利用可能だった認証情報と露出期間の特定 | 無効化と調査の対象を確定する | 棚卸し表に基づく認証情報の一覧、悪意のあるバージョンが最初に実行された日時から無効化までの期間 |
| 認証情報の無効化・更新 | 窃取された認証情報の利用を止める | 長期キーの無効化、一時認証情報のセッションの取り消し、再取得経路の遮断 |
| クラウド側の調査 | 不正な操作の有無と範囲を確認する | 権限の変更、新しい認証情報、信頼関係、データアクセス、監査設定の変更 |
端末の隔離や停止でメモリなどの揮発性の情報が失われる場合はありますが、クラウドの監査ログは認証情報を無効化しても失われません。ログの保全が終わるまで無効化を待つのではなく、進行中の被害の大きさに応じて遮断のタイミングを判断してください。
認証情報の無効化で見落としやすい点
AWS の IAM ユーザーのアクセスキーは、無効化または削除によって以後の利用を止められます。一方、一時的なセキュリティ認証情報は有効期限まで使えるため、ロールについてはセッションの取り消しを検討します。AWS の手順では、ロールに拒否ポリシーを付与し、指定時刻より前に発行されたセッションのアクセス許可を取り消します。
参考: AWS IAM ユーザーガイド「IAM ロールの一時的なセキュリティ認証情報を取り消す」
「アクセス許可が取り消された後にユーザーがロールを引き受けた場合、拒否ポリシーはそのユーザーに適用されません。」
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_use_revoke-sessions.html
つまり、セッションを取り消しても、攻撃者が再びロールを引き受けられる経路が残っていれば、新しい認証情報を取得できます。OIDC の信頼条件、侵害された端末やランナーに割り当てられたロール、窃取された長期キーから引き受けられるロールなど、再取得の経路もあわせて止める必要があります。特定のセッションだけを拒否する方法や、リソースベースのポリシーで明示的な拒否を追加する必要がある場合については、一時的なセキュリティ認証情報のアクセス権限を無効にするに手順があります。
GitHub の PAT は失効させ、必要に応じて最小のスコープで再発行します。GitHub Actions の Secrets は値を更新するだけでなく、更新後の値が同じジョブ構成で再び渡らないよう、前述のジョブ分離を見直します。Azure のサービスプリンシパルや Google Cloud のサービスアカウントキーも、資格情報の削除・無効化に加えて、ロールの割り当てや権限借用が可能な関係を確認します。
対応完了と判断する前に、次のような判断が残っていないかを確認します。
- 「悪意のあるパッケージを削除した」
-
パッケージを削除しても、別の場所に配置されたペイロードや永続化の仕組みが動作し続ける場合があります。窃取済みの認証情報と、端末やランナーに残ったペイロードへの対応は、削除とは別に必要です。
- 「元のアクセスキーを更新した」
-
攻撃者が作成した新しいアクセスキー、追加されたユーザーやロール、変更された信頼ポリシーが残っていれば、アクセスは継続します。
- 「OIDC なので保存されたキーはない」
-
侵害されたジョブで取得された一時認証情報は、有効期限まで使える可能性があります。セッションの取り消しと信頼条件の見直しを確認します。
- 「監査ログに不審な操作が見当たらない」
-
記録していない種類の操作や、保存期間外の操作はログに現れません。調査したログの種類、期間、リージョンを明記したうえで判断します。
クラウド側で調べる操作とログの範囲
調査は、露出した認証情報の識別子(アクセスキー ID、ロール ARN など)を起点に、その権限で可能だった操作を確認します。管理操作のログとデータアクセスのログは記録の仕組みが異なるため、分けて確認します。
| 調査の観点 | AWS での確認例 | 主なログ |
|---|---|---|
| 権限の変更 | AttachRolePolicy、CreateRole、CreateUser | CloudTrail の管理イベント |
| 新しい認証情報 | CreateAccessKey、CreateLoginProfile | CloudTrail の管理イベント |
| 信頼関係の変更 | UpdateAssumeRolePolicy、CreateOpenIDConnectProvider | CloudTrail の管理イベント |
| 監査設定の変更 | StopLogging、DeleteTrail、UpdateTrail | CloudTrail の管理イベント |
| データアクセス | S3 のオブジェクトの取得(GetObject) | CloudTrail のデータイベント(証跡やイベントデータストアで事前に記録を有効にしている場合) |
CloudTrail のイベント履歴は追加設定なしで利用できますが、対象は直近 90 日の管理イベントで、検索はアカウントとリージョンごとに行います。
参考: AWS CloudTrail ユーザーガイド「Working with CloudTrail event history」
“It does not show data events, Insights events, or network activity events.”
(データイベント、Insights イベント、ネットワークアクティビティイベントは表示されません。)
https://docs.aws.amazon.com/awscloudtrail/latest/userguide/view-cloudtrail-events.html
露出したアクセスキーによる管理操作は、イベント履歴を次のように検索して確認できます(AWS CloudTrail ユーザーガイド)。指定できる属性は一度に一つで、結果はリージョン単位のため、利用しているリージョンごとに実行します。
aws cloudtrail lookup-events \
--region ap-northeast-1 \
--lookup-attributes AttributeKey=AccessKeyId,AttributeValue=<アクセスキー ID> \
--start-time 2026-09-01T00:00:00Z検索するリージョンにも注意が必要です。IAM などのグローバルサービスのイベントは米国東部(バージニア北部、us-east-1)のイベントとして記録されるため、アクセスキーの作成や権限の変更を調べる際は、普段リソースを運用しているリージョンだけでなく us-east-1 も確認します。一方、STS はグローバルエンドポイントとリージョンエンドポイントのどちらを使ったかによって、イベントが記録されるリージョンが異なります(AWS CloudTrail ユーザーガイド)。
また、長期のアクセスキーで AssumeRole を実行した後の操作は、発行された一時認証情報のアクセスキー ID で記録されます(CloudTrail の userIdentity 要素)。元のキー ID で検索すると AssumeRole などの発行イベントは見つかりますが、その後の操作は同じ検索では追いきれません。発行イベントの応答に含まれる一時認証情報のアクセスキー ID、引き受け先のロール、セッション名をたどり、別アカウントのロールを引き受けていた場合は、そのアカウント側のログも調査します。なお、userIdentity のアクセスキー ID は記録されない場合や空の場合もあるため、ロール ARN やセッション名も手がかりにします。
複数のアカウントやリージョンを横断する場合、90 日より前の操作やデータイベントを調べる場合は、証跡の保存先や CloudTrail Lake のイベントデータストアを使います。ログを収集していない期間や種類については「侵害なし」と判断せず、確認できなかった範囲として記録してください。Azure や Google Cloud を利用している場合も同じ観点で調査しますが、記録される操作の種類と既定の保存期間はサービスごとに異なるため、それぞれの公式資料で確認が必要です。
復旧と継続監視
悪意のあるコードは、端末やランナーに永続化の仕組みを残している可能性があります。GitHub は、セルフホスト型ランナーがクリーンな環境で実行される保証はないとしているため、侵害が疑われるランナーは既知の正常なイメージから再構築することをおすすめします。開発端末についても、調査結果に応じて再構築を検討します。
復旧後は、新しい認証情報でビルドとデプロイが正常に動作することを確認します。あわせて、無効化した古いキー ID やロールによるアクセスの試行、調査後に新たに作成されたリソースの有無を一定期間監視します。
まとめ
開発端末や CI/CD で実行された悪意のあるコードは、その環境から使える認証情報の権限の範囲で、クラウド環境に影響を及ぼします。予防と侵害時の対応のどちらも、実行環境、認証情報、クラウド資源の対応関係を把握していることが前提になります。
- インストールやビルドの時点で、アプリの起動前にコードが実行される場合がある。
- 影響判断では、依存関係への包含、インストール、コード実行、窃取を区別する。
- 認証情報は識別子と権限、利用履歴で棚卸しし、値そのものは表示しない。
- 依存関係の取得やビルドのジョブと、クラウド権限を持つデプロイを分離する。
- OIDC、IMDSv2、MFA、SHA ピン留めは、それぞれ単独では経路を防ぎきれない。
- 初動では遮断と保全を並行し、セッションの取り消しと再取得経路も止める。
- 監査ログがない期間や種類は、侵害がなかった根拠にはならない。
以上、最後までお読みいただきありがとうございました。

