flawopen.com/AI Security/plugin4shell-ai-agent-plugin-sha-pin-bypass
●
CWE-345 · 高
セキュリティ研究 · FlawOpen
Plugin4Shell:プラグインSHA固定の回避
4種類のAIエージェント用プラグインインストーラーは、Gitリビジョンを固定してもcheckout後のcommitを検証しませんでした。Plugin4Shellの教訓は最終SHAの確認です。[1]
💡 わかりやすい解説 (ELI5)
図書館が本の特定の版を固有の蔵書番号で取り置きします。係員はその番号を指定しますが、棚札に同じ文字が書かれていると別の本を渡してしまいます。SHA ピンは蔵書番号です。インストーラーはプラグインを信頼したり実行したりする前に、実際に checkout された commit を確認する必要があります。[1]
主要な概念と専門用語
Git ref の曖昧性- Git はオブジェクト ID とブランチ名などをリビジョン式として扱います。条件によっては、commit ID のような名前が ref として解決されます。[1]
プラグインマーケットプレイス- エージェント拡張を配布し、審査済みリビジョンを記録するカタログです。ピンを強制する責任はインストール側にもあります。[1]
CWE-345- データの真正性検証不足です。システムが、データが期待された真正な値であるかを十分確認せずに利用します。[5]
フレームワーク対応
- このガイドで説明する弱点の CWE 参照: CWE-345
ステップ・バイ・ステップの攻撃フロー
ソースコード比較:脆弱 vs 堅牢化
脆弱な経路は、名前の解決に成功したことをオブジェクトの同一性の証明と取り違えていました。修正は checkout 後の HEAD をマーケットプレイスのピンと比較し、別の commit の展開を拒否します。このコードは Codex の修正を示しています。他製品は別実装のため、同じ修正があると推定してはいけません。[2], [6]
脆弱な実装
// OpenAI Codex PR #34644 の修正前の形
if let Some(target) = sha.or(ref_name) {
run_git(&["checkout", target], Some(destination))?;
}
// checkout の成功を SHA 一致の証明として扱っていた。
堅牢化されたセキュアパッチ
// Codex の修正:要求引数だけでなく、解決後の commit を検証する
if let Some(sha) = sha {
run_git(&["checkout", sha], Some(destination))?;
let checked_out_sha =
run_git_output(&["rev-parse", "HEAD"], Some(destination))?;
if !checked_out_sha.eq_ignore_ascii_case(sha) {
return Err(format!(
"checked out Git SHA {checked_out_sha} does not match requested SHA {sha}"
));
}
} else if let Some(ref_name) = ref_name {
run_git(&["checkout", ref_name], Some(destination))?;
}
エンジニアリング&システム堅牢化チェックリスト
- ✓SHA 固定の checkout ごとに、実際に選択された commit(例:<code>git rev-parse HEAD</code>)を解決し、プラグインファイルを読み込む前に要求されたピンと完全一致するか確認する。[2], [6]
- ✓FlawOpenの実装上の推奨事項:不一致、HEAD 欠落、コマンドエラー、想定外のリビジョン形式では fail closed とし、ブランチ名にフォールバックしない。[2]
- ✓デフォルトブランチ名が別 commit の SHA と衝突する一時的なローカルリポジトリでテストし、インストールが拒否されプラグインコードが読み込まれないことを確認する。[6]
- ✓FlawOpenの実装上の推奨事項:型と制御フローで ref 名と不変の SHA ピンを分離し、検証済み commit をインストールメタデータに記録する。[1]
- ✓影響を受けるエージェントのバージョンとマーケットプレイスの Git ホストを棚卸しする。GitHub は SHA 形式のブランチ名を拒否しますが、そのホスト固有ルールは他の対応ホストや Gemini の FETCH_HEAD 経路を保護しません。[1], [4]
- ✓引用したAIRの開示では、Codexは0.146.0、Claude Codeは2.1.179で修正されたとされていますが、影響を受ける全バージョンの範囲は示されていません。CopilotやGemini CLIの状態や対策を案内する前に、各ベンダーの最新情報を確認してください。[1], [3], [7]
- ✓Codexの回帰テスト
materialize_git_source_rejects_sha_that_resolves_to_hostile_default_branchを維持します。このテストは一時的なローカルリポジトリを作成し、プラグインソースのマテリアライズ前にHEADの不一致が拒否されることを確認します。[6]