FlawOpen

flawopen.com/Teardowns/cve-2026-25592-semantic-kernel-agent-file-write

● CVE-2026-25592 · CVSS 9.9[2], [4] · 緊急
セキュリティ研究 · FlawOpen

CVE-2026-25592:Semantic Kernel のファイル書き込み

CVE-2026-25592 は Semantic Kernel のダウンロード機能を AI ツールとして公開し、ホストへの書き込みを可能にしました。モデルのアクセスを外し、1.71.0 以降へ更新してください。[2]

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

宅配係は、施錠された試験室から会社のオフィスへ荷物を運べます。本来は社員からの依頼だけを受けるはずですが、AI アシスタントの指示にも従う名札を付けていました。悪意あるメモで、アシスタントにオフィスの引き出しを配送先として選ばせることができます。修正では、モデルがこのヘルパーを呼び出せる名札を外します。アプリケーションから呼び出す場合も、保存先を制限する必要があります。[1], [2]

主要な概念と専門用語

KernelFunction
Semantic Kernel の属性。メソッドをモデルが呼び出せるツールとして公開します。[1], [2]
SessionsPythonPlugin
エージェントが隔離されたリモート Python セッション内のコードとやり取りするための Semantic Kernel プラグインです。[1], [2]
localFilePath
DownloadFileAsync に渡す、ホスト側の任意の保存先パスです。[1], [2]
パス許可リスト
明示的に設定し正規化したディレクトリ配下への書き込みだけを許可するポリシーです。[1], [2], [5]

フレームワーク対応

  • このガイドで説明する弱点の CWE 参照: CWE-22

根本原因の分析 (Root Cause)

.NET 版 Semantic Kernel の SessionsPythonPlugin は、リモート Python セッションとアプリケーションのホストを接続します。DownloadFileAsync はセッションからファイルを取得し、返されたバイト列をホスト上の localFilePath に保存できます。このメソッドには KernelFunction 属性が付いており、モデルがツールを選ぶ際に引数も公開されていました。攻撃者がエージェントへの入力に影響できる場合、意図しない保存先でヘルパーを呼び出させようとする可能性があります。これはツール認可とパス境界の不備であり、言語モデル自体の欠陥でも、リモート Python セッションの sandbox 脱出でもありません。Microsoft の修正は DownloadFileAsync から KernelFunction を削除し、モデルが呼び出せないようにします。アプリケーションコードがこのヘルパーを使う場合は、許可ディレクトリの明示的なポリシーを設定して強制してください。許可ディレクトリ一覧が空の場合、upstream 実装は制限なしです。GHSA-2ww3-72rp-wpp4 は NuGet の Microsoft.SemanticKernel.Plugins.Core 1.71.0 未満に加え、PyPI の semantic-kernel 1.39.3 未満も列挙しています。本記事は Microsoft が説明した .NET の攻撃経路に焦点を当てます。[1], [2], [3]

パッケージの対象範囲と修正済みバージョン

パッケージ / 対象範囲影響を受けるバージョンと修正済みバージョンこの記事で扱う内容
.NET Microsoft.SemanticKernel.Plugins.Core影響あり: < 1.71.0、修正済み: 1.71.0 以降。文書化された SessionsPythonPlugin の連鎖です。モデルから呼び出せる DownloadFileAsync が、セッションデータをホスト上のパスに書き込む可能性がありました。
Python semantic-kernel影響あり: < 1.39.3、修正済み: 1.39.3 以降。アドバイザリにはこのパッケージも記載されています。この記事では Python 固有の攻撃経路は分析しません。Python パッケージも個別に更新してください。
セッションファイルを意図的にホストへ保存するアプリモデルからの呼び出しをなくした後も保存先を制限します。Function Invocation Filter または同等の認可レイヤーで、正規化したパスの明示的な許可リストを使います。上流実装では AllowedDownloadDirectories が空だと任意の絶対パスが許可されます。

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

ステップ 1

信頼できない内容がエージェントに影響する

攻撃者は、処理対象のコンテンツなどを通じてエージェントの入力に影響を与える必要があります。Microsoft が文書化した連鎖では、最初のツール呼び出しでファイルを分離されたリモート Python セッションに置きます。この段階ではファイルはセッション内に留まります。[1], [2]

ステップ 2

モデルにホスト側ヘルパーが見える

影響を受ける .NET 構成では、KernelFunction によって DownloadFileAsync がモデル呼び出し可能なツールに含まれていました。[1], [2]

ステップ 3

引数が信頼境界を越える

モデルはリモートセッションからファイルを取得する際に localFilePath を選べました。そのパスはホストプロセスで処理されます。[1], [2]

ステップ 4

ホストへの書き込みが可能になる

ホストへの書き込みには、モデルが信頼できない入力の影響を受けた localFilePath を使ってこのヘルパーを呼び出し、そのパスが実効性のある許可ディレクトリ制限の外にあることが必要です。Microsoft が示したのは制御された研究上の連鎖であり、広範な悪用の報告ではありません。[1], [2]

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

upstream 修正では DownloadFileAsync から KernelFunction 属性を削除し、ツール登録の境界でモデルからの到達性を断ちます。メソッドのシグネチャはアプリケーションが意図的に使うために残ります。advisory は Function Invocation Filter と明示的なパス許可リストで DownloadFileAsync および UploadFileAsync の引数を検証することも推奨しています。Path.GetFullPath だけでは認可になりません。また、upstream 実装では AllowedDownloadDirectories が空だと制限がありません。[2], [3]

ソース抜粋: 対象メソッド:`SessionsPythonPlugin` の `DownloadFileAsync`

脆弱な実装
[KernelFunction, Description("Downloads a file from the current session.")]
public abstract Task<byte[]> DownloadFileAsync(
    string remoteFileName,
    string? localFilePath = null,
    CancellationToken cancellationToken = default);
堅牢化されたセキュアパッチ
[Description("Downloads a file from the current session.")]
public abstract Task<byte[]> DownloadFileAsync(
    string remoteFileName,
    string? localFilePath = null,
    CancellationToken cancellationToken = default);

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

参考資料