GoogleがCodeMenderの参照構成を紹介、プルリクエストで脆弱性の検証と修正が可能
公開:
Googleは、CodeMenderによる自動修正をGoogle Cloud Run経由でGitのプルリクエストへ組み込む参照アーキテクチャを公開しました。CodeMenderは、ソフトウェアの欠陥を機械の速さで見つけて修正できる、Googleの自律型コードセキュリティエージェントです。[1]
この記事では、参照アーキテクチャでCodeMenderをプルリクエストへ組み込むとできることと、導入前の確認事項を解説します。検証用の攻撃コードをCloud Run jobで実行する点も、確認事項として整理します。
参照アーキテクチャでのプルリクエスト操作
参照アーキテクチャでは、プルリクエストをきっかけにCloud Run上でスキャンが動きます。スキャンは1件のコメントを投稿し、IDの付いた検出結果の表と、次に入力できる2つのコマンドを示します。[1]
検出結果や攻撃の試行記録、修正案の返る先は、同じタイムラインです。開発者は、プルリクエストを離れることも、コンソールの使い方を覚えることも求められません。
サンドボックスでの攻撃検証
CodeMenderのcm findは、コード解析の際に脆弱性の検出結果へ確信度のスコアを返します。スコアが100%未満の場合に、サンドボックスで攻撃を組み立てて模擬し、実際に悪用できるかを確かめる手段がcm verifyです。
プルリクエストでは、/verify 612424daのようにIDを付けて返信すると、サンドボックスでの攻撃試行の記録がスレッドに届きます。記録はView Exploit Steps & Response Traceという折りたためる枠に入り、会話を埋もれさせません。
模擬攻撃の結果によって、深刻度が変わることがあります。検証用のサンドボックスは一時的なため、パイプラインは記録を監査証跡としてGoogle Cloud Storageへ自動で送ります。
修正パッチによる対応
攻撃によって検出結果が本物だと示された場合、次の手順はチケットではなくパッチの作成です。cm fix a1b2c3d4のようにIDを指定すると、CodeMenderがパッチを作成する仕組みです。
プルリクエストでは、/fix 612424daと返信すると、統合形式の差分がPreview Proposed Code Diffという枠に入って届きます。/approveする下書きのプルリクエストもすでに開いており、/verifyと/fixはIDの代わりにallも指定できます。
差分に問題がなければ、適用は開発者が/approveと返信する1回の操作です。エージェントはパッチをブランチにコミットしてプッシュし、コミット状態security/codemender-gateを緑に設定します。
コミット状態をマージの阻止に変えるのは、ブランチ保護の役割です。ブランチ保護を設定していない場合、ゲートは参考扱いにとどまります。
CodeMender参照実装を動かす前提
CodeMenderを使った自律型のGitOpsセキュリティエージェントは、参照実装codemender-gitopsから構築を始められます。動かす前提として、GitHubとGoogle Cloudが互いを信頼する設定が必要です。[1]
OIDCトークンでの認証
このエージェントにはソースコードへの書き込み権限が必要で、その認証情報をシークレットの保管場所に置くと漏えいのおそれがあります。GitHub Actionsが発行する短期のOIDCトークンを受け入れるようGoogle側を設定すれば、盗まれる長期の認証情報が残りません。
受け入れるリポジトリの限定
この構成の安全性は、ほぼ1行の条件設定にかかっています。以下は、GitHub Actionsを発行元とし、特定のrepository_idに限定する定義です。
resource "google_iam_workload_identity_pool_provider" "github" {
workload_identity_pool_provider_id = "github-provider"
oidc {
issuer_uri = "https://token.actions.githubusercontent.com"
}
attribute_mapping = {
"google.subject" = "assertion.sub"
"attribute.repository_id" = "assertion.repository_id"
}
# Without this, any repository on GitHub can exchange a token against your pool
attribute_condition = "assertion.repository_id == '123456789'"
}
公式資料からの抜粋:Don't just flag it, fix it: How to run CodeMender in your pull requests(No stored keys between GitHub and Cloud Run)。対象版・範囲:原記事の参照アーキテクチャのコード例(版の記載なし)。
上記のコードでは、issuer_uriで発行元を指定し、attribute_conditionで受け入れるrepository_idを1つに限定しています。attribute_conditionが無い場合、GitHub上の任意のリポジトリがこのプールに対してトークンを交換できます。
発行元URLはGitHub Actionsのワークフロー間で共通のため、発行元の確認だけでは守りになりません。リポジトリを絞る働きを担うのは、attribute_conditionの条件です。
照合にはassertion.repositoryも使えますが、リポジトリ名は変更されたり、手放した後に他者に取得されたりします。Googleは、変更されないrepository_idとrepository_owner_idの対応付けを推奨しています。
CodeMender参照アーキテクチャの確認点
CodeMenderはAI Threat Defenseプラットフォームの一部で、今回の発表はプルリクエストへ組み込む参照アーキテクチャと参照実装です。CodeMenderの料金や提供地域、提供状態は、今回の発表に含まれていません。[1]
コミット状態security/codemender-gateでマージを止めたい場合は、対象ブランチのブランチ保護を確かめます。GitHubのOIDCトークンをGoogle側で受け入れる場合は、attribute_conditionの対象を自分のrepository_idに絞ったかも確認対象です。
検証パイプラインの判定設計
自前の検証パイプラインでは、テストが失敗したときの扱いの設計が欠かせません。ハーネスが攻撃成功の文字列だけを探す作りでは、モックサーバーのクラッシュやタイムアウトで、本物の脆弱性が安全と誤判定されるおそれがあります。
Googleは、パーサーで真の陰性の結果とテストのクラッシュを区別することを勧めています。攻撃が正常に完了しなかった場合は、問題なしとせず、状態をinconclusiveとして示す設計です。
検証の判定をレビューの根拠に使う場合は、自前のパーサーがテストのクラッシュと真の陰性を分けているかを確かめます。攻撃成功の文字列だけを探す作りでは、テストの失敗が安全という判定につながるおそれがあるためです。
Cloud Run jobの実行設計
検証では、誰もレビューしていない攻撃コードをその場で書き、脆弱性の種類が示す動作をモックの標的に向けて行う仕組みです。自律型エージェントがコンテナを抜け出し、内部ネットワークをポートスキャンする事態は避ける必要があります。
Googleの構成では、攻撃コードは何も保持しないインスタンスで動き、インスタンスは検出結果1件の間だけ存在して、外へ出るのは判定結果だけです。記録をGoogle Cloud Storageへ送るパイプラインと、このインスタンスとの関係(記録の送信元)は今回の発表に含まれていません。
判定を信頼する前に、攻撃コードをどこで実行し、実行中に何へ届くかを確かめる必要があります。Googleが示す実行場所はCloud Run jobで、検出結果1件ごとにjobを1つ実行し、終了後に残るのは判定結果だけです。
Cloud Runのインスタンスはサンドボックス化され、jobは常にLinux完全互換のmicroVMである第2世代実行環境で動きます。jobの実行は開始して1つの処理を行い、そこで終了する流れです。
どちらかのsandboxesによる分離
Cloud Run sandboxesまたはagent sandboxesを使うと、インスタンス内のプロセスの実行が親のワークロードから分離されます。プロセスは環境変数やシークレット、Google Cloudのメタデータサーバーからも分離され、プラットフォームが既定で渡す認証情報にも届きません。
攻撃コードの到達範囲の設計
jobには専用のサービスアカウントを持たせ、エクスプロイトを書き込むAPI以外の権限は与えない構成です。Googleの構成では、組織のポリシーによってはroles/editorを持つことがあるCompute Engineのデフォルトアカウントを使いません。
Cloud Runはデプロイ時にコンテナイメージを取り込むため、jobにはレジストリへのアクセス権も不要です。ネットワークはDirect VPC egressで外へ出る経路のないサブネットにつなぎ、見つけた情報の持ち出しや第2段階の攻撃コードの取得を防ぎます。
攻撃コードをCloud Run jobで実行する検証環境では、jobにCompute Engineのデフォルトアカウントを使っていないかを確かめます。サブネットに外へ出る経路が残っていないかも、あわせて確かめる対象です。
出典
- ^ Google Cloud. 「Don't just flag it, fix it: How to run CodeMender in your pull requests」. https://cloud.google.com/blog/products/identity-security/how-to-run-codemender-in-your-pull-requests, (参照 26-11-10).
※本記事は公式の一次情報を基に編集しています。内容はAIで確認していますが、誤りや最新情報との差異がある場合は、以下フォームよりご報告ください。
修正・削除・掲載などの依頼はこちら





















