FlawOpen

flawopen.com/Teardowns/cve-2026-87913-aws-security-agent-mcp-s3-bucket-ownership

● CVE-2026-87913 · CVSS 5.1 · 中
セキュリティ研究 · FlawOpen

CVE-2026-87913:AWS MCP の S3 情報漏えい

AWS Security Agent の予測可能な S3 バケットに、非公開のソーススキャン用アーカイブが別アカウントへ送信される可能性がありました。0.2.0 へ更新し、実際のバケット所有者を確認してください。[1], [2], [4]

💡 わかりやすい解説 (ELI5)

配達員が住所に建物があるかだけを確認し、所有者を調べない状況を想像してください。別の人が先に住所を登録して荷物を受け取れます。修正では S3 に確認時とアップロード時の両方で所有者を検証させます。[2], [1]

主要な概念と専門用語

MCP サーバー
AI アシスタント向けに操作をツールとして提供するローカルサービス。サーバープロセスの権限で動きます。[3]
S3 バケット
グローバルに一意な名前を持つ Amazon S3 のコンテナ。名前だけでは所有 AWS アカウントは分かりません。[2], [3]
ExpectedBucketOwner
操作前に期待する所有アカウント ID を S3 に検証させるリクエストパラメーター。[2], [8], [9]
CWE-283 と CWE-341
所有権未確認と観測情報から予測可能な値を表す MITRE 分類で、通知は両方を割り当てています。[8], [9]

フレームワーク対応

根本原因の分析 (Root Cause)

AWS Security Agent MCP サーバーは、顧客の AWS アカウント ID とリージョンからスキャン用バケット名 security-agent-scans-<account-id>-<region> を生成します。AWS とメンテナーの通知によると、脆弱版はバケットの存在を確認しましたが、顧客アカウントの所有物かは検証していませんでした。S3 名はグローバルに一意で、アカウント ID は公開情報です。第三者が予測可能な名前を先に登録すると、サーバーがアップロードする非公開アーカイブを受け取る可能性があり、ソース、認証情報、インフラ状態が含まれ得ます。これはクラウド資源の所有確認不足と予測可能な名前の問題で、AIモデルのプロンプトインジェクションではありません。対象は 0.1.0〜0.1.5、0.2.0 は S3 操作に ExpectedBucketOwner を加え、不一致時に失敗します。更新しても既登録の名前は解放されません。実際の所有者を確認し、第三者所有ならスキャンを再開しないでください。

バケット名だけでは所有者を確認できない

境界文書化された条件運用担当者の対応
影響を受けるバージョンawslabs.security-agent-mcp-server 0.1.0〜0.1.5 が影響を受け、0.2.0 で所有者確認が追加された。0.2.0 以降へアップグレードし、実行中のパッケージバージョンを確認する。
予測可能なバケット名スキャン用バケット名はアカウント ID とリージョンから生成され、別の AWS アカウントが先に登録できる。一致する名前はアドレスとして扱い、所有権の証明とはみなさない。
アカウント間アップロード脆弱なサーバーは所有者を確認せず名前だけでバケットを受け入れ、非公開のスキャンアーカイブをアップロードする可能性があった。スキャンまたはアップロードの前に、バケットが想定アカウントの所有物であることを確認する。
修正された所有権境界ExpectedBucketOwner により、S3 は所有権確認時とアップロード時の両方で所有者を照合する。更新後に実際の所有者を確認する。第三者が名前を所有している場合はスキャンを停止する。アップグレードでバケットは移転しない。

ステップ・バイ・ステップの攻撃フロー

ステップ 1

スキャン要求がソースを受け取る

AI クライアントがスキャンを依頼し、ローカルサーバーは AWS ID を使って作業領域をまとめます。[3], [2]

ステップ 2

宛先名が予測できる

名前はアカウント ID とリージョンから決まります。ID は秘密ではなく S3 名はグローバルです。[1], [2]

ステップ 3

確認は存在しか見ない

脆弱版は名前でバケットを受け入れ、顧客所有かを確認しませんでした。[2], [1]

ステップ 4

アーカイブが別アカウントへ届く可能性

他者が名前を先に登録していれば、機密情報を含む非公開アーカイブが届く可能性があります。[2], [1]

ソースコード比較:脆弱 vs 堅牢化

以下は模式例であり、逐語的なソースではありません。存在確認だけでは不十分です。S3 は確認時と書き込み時に期待所有者を照合する必要があります。認証済み AWS ID から期待値を取得し、不一致なら中断します。更新後も所有者を別途確認してください。登録済みの名前は更新だけでは譲渡・解放されません。 AWSの資料ではHeadBucketとPutObjectの両方でExpectedBucketOwnerがサポートされ、所有者が一致しない場合は403で失敗します。fail-closedのガードとして使えますが、バケットが他者所有だと判断する前に、認可された所有者確認経路でアクセス拒否エラーを調査してください。[2], [8], [9]

ソース抜粋: アドバイザリに基づくAWS SDKの例であり、逐語的なソース差分ではありません。

脆弱な実装
# 脆弱な処理の簡略例:名前は確認しますが、所有者は確認しません。
s3.head_bucket(Bucket=bucket_name)
s3.put_object(
    Bucket=bucket_name,
    Key=object_key,
    Body=archive_bytes,
)
堅牢化されたセキュアパッチ
# 各操作を想定するバケット所有者のアカウントに紐付けます。
expected_owner = sts.get_caller_identity()["Account"]
s3.head_bucket(
    Bucket=bucket_name,
    ExpectedBucketOwner=expected_owner,
)
s3.put_object(
    Bucket=bucket_name,
    Key=object_key,
    Body=archive_bytes,
    ExpectedBucketOwner=expected_owner,
)

エンジニアリング&システム堅牢化チェックリスト

参考資料